**타입 단언(type assertion)**은 interface 값에서 구체 타입을 추출하고, **타입 스위치(type switch)**는 interface의 기반 타입에 따라 분기합니다. interface(특히 빈 interface / any)에서 특정 타입 정보를 되찾는 방법입니다.
타입 단언 — 구체 타입 추출
i {} =
s := i.()
fmt.Println(s)
n := i.()
i.(Type) 문법은 interface i가 Type의 값을 담고 있다고 단언하고 추출합니다. 하지만 잘못된 단언은 panic합니다 — 그래서 보통 안전한 comma-ok 형태를 씁니다.
s, ok := i.(string)
if ok {
fmt.Println("it's a string:", s) // ok = true, s = 값
} else {
fmt.Println("not a string") // ok = false, s = 제로값, panic 없음
}
두 값 형태는 값과 불리언을 반환합니다 — 단언이 실패하면 (panic 대신) ok가 false입니다. 타입을 확신하지 않는 한 항상 이것을 선호하세요.
func describe(i interface{}) string {
switch v := i.(type) { // 특별한 .(type) 형태, switch에서만
case int:
return fmt.Sprintf("int: %d (doubled: %d)", v, v*2)
case string:
return fmt.Sprintf("string of length %d", len(v))
case bool:
return fmt.Sprintf("bool: %t", v)
case nil:
return "nil value"
default:
return fmt.Sprintf("unknown type: %T", v)
}
}
describe(42) // "int: 42 (doubled: 84)"
describe("hi") // "string of length 2"
switch v := i.(type) 형태는 기반 타입을 확인하고 v를 바인딩합니다(각 case에서 적절히 타입 지정). interface가 여러 타입을 담을 수 있을 때 처리하는 깔끔한 방법입니다.
// 값이 특정 interface를 구현하는지 단언
if w, ok := i.(io.Writer); ok {
w.Write([]byte("data")) // 그 interface를 충족하면 io.Writer로 사용
}
✓ 알 수 없는 타입의 값 처리(interface{}/any) — JSON, 제네릭 핸들러
✓ 값이 선택적 interface를 구현하는지 확인(예: io.Closer)
✓ 이질적 데이터 처리
⚠️ 종종 제네릭이나 더 잘 타입 지정된 interface를 쓸 수 있다는 신호 — 과용 금지
타입 단언과 타입 스위치는 interface 값으로 작업하는 데 필수 도구입니다 — interface{}/any에서 구체 타입 정보를 되찾거나 값이 특정 interface를 충족하는지 확인합니다.
알 수 없거나 다양한 타입의 데이터를 처리할 때 필요합니다(동적 JSON 파싱, 제네릭 처리, "이것이 io.Closer를 구현하는가?" 같은 선택적 interface 확인).
panic vs 안전 구별을 이해하는 것이 결정적입니다: 평범한 단언 i.(T)는 불일치 시 panic하고, comma-ok 형태 v, ok := i.(T)는 안전하게 실패를 보고합니다 — 안전한 형태를 쓰는 것이 런타임 크래시를 피하는 핵심 관행입니다.
타입 스위치는 여러 가능한 타입을 우아하게 처리합니다.
이것들을(그리고 과도한 사용이 종종 제네릭이나 더 잘 타입 지정된 설계를 써야 한다는 신호임을) 아는 것은 안전하고 관용적인 Go에 중요하며 흔한 면접 주제입니다. interface와 빈 interface가 언어에 너무나 핵심적이기 때문입니다.
주니어부터 시니어까지 상세한 답변이 포함된 IT 면접 질문 라이브러리.
후원하기