Switch
일반적으로 다른 언어에서는 어떤 값의 타입에 따라 다른 행동을 하고 싶을 때 Reflection
를 사용하여 해결한다. Go 에서는 특이하게도 언어차원에서 Switch
를 사용하여 해결할 수 있는데, 다음과 같이 해볼 수 있다.
var t interface{} = map[string]string{
"sayHello": "Hello, Go!",
}
switch t := t.(type) {
case string:
fmt.Println(t)
case map[string]string:
for k, v := range t {
fmt.Println(k, v)
}
}
Switch
와 함께 타입 단언(Type Assertion)을 사용하여 해결할 수 있다. 그런데 자세히 살펴보면 map
타입에 대해서는 상당히 불편한 사항을 발견할 수 있는데, 키와 값의 타입이 반드시 지정이 되어 있어야 체크가 가능하다는 점이 바로 그것이다.
reflect 패키지로 타입 체크하기
키와 값에 구분없이 단순히 포인터인 경우, 맵인 경우와 같이 종류만으로만 점검하고 싶다면 reflect
패키지를 사용하면 해결할 수 있다. reflect
패키지를 사용하여 타입을 체크하면 다음과 같이 바꿀 수 있다. 이렇게 바꾸면 맵 타입에 대해 키와 값 타입에 상관없이 체크가 가능하다.
t := map[string]string{
"sayHello": "Hello, Go!",
}
switch rv := reflect.ValueOf(t); rv.Kind() {
case reflect.String:
fmt.Println(rv.String())
case reflect.Map:
for k, v := range t {
fmt.Println(k, v)
}
}
reflect.ValueOf()
함수는 reflect.Value
를 반환하는데, 이 타입의 메서드들은 우리가 값으로 넘긴 것에 대한 값 자체에 대한 정보가 담겨있다. 여기서 Value.Kind()
메서드를 쓰면 해당 값의 종류를 알 수 있다. 리턴하는 값은 reflect.Kind
타입을 가진다. Kind
는 Type
과는 다른데, Value.Type().String()
으로 하게 되면 map[string]string
이 나올 것이고, Value.Kind().String()
를 사용하게 되면 map
이 나온다.