더북(TheBook)

7.3.6 리플렉션

reflect 패키지를 사용하면 프로그램의 메타 데이터를 활용하여 객체를 동적으로 제어할 수 있다. 즉, 런타임 시 타입이 정해지지 않은 값의 실제 타입을 확인하여 그 값의 메서드를 호출하거나 내부 필드에 접근할 수 있다. reflect 패키지의 주요 기능을 살펴보자.

 

타입/값 정보 확인

Go의 모든 값은 요소 두 개로 구성된다. 하나는 값의 타입이고 또 하나는 실제 값이다. 타입은 reflect.TypeOf() 함수로 확인하고, 실제 값은 reflect.ValueOf() 함수로 확인한다.


x := 1
y := 1.1
z := "one"
 
fmt.Printf("x: %v(%v)\n", reflect.ValueOf(x).Int(), reflect.TypeOf(x))
fmt.Printf("y: %v(%v)\n", reflect.ValueOf(y).Float(), reflect.TypeOf(y))
fmt.Printf("z: %v(%v)\n", reflect.ValueOf(z).String(), reflect.TypeOf(z))

실행 결과

x: 1(int)

y: 1.1(float64)

z: one(string)

reflect.ValueOf() 함수는 실제 값의 정보를 담고 있는 reflect.Value 타입 값을 반환한다. reflect.Value 타입에는 reflect.Value.Bool(), reflect.Value.Complex(), reflect.Value.Float(), reflect.Value.Int(), reflect.Value.String()처럼 실제 값을 확인하는 메서드가 있다.

슬라이스와 맵 같은 컬렉션 타입이나 구조체도 리플렉션으로 메타 정보를 확인할 수 있다. 구조체의 태그 정보에 접근할 때도 리플렉션을 사용한다.


type User struct {
    Name string "check:len(3,40)"
    Id   int    "check:range(1,999999)"
}
 
u := User{"Jang", 1}
uType := reflect.TypeOf(u)
 
if fName, ok := uType.FieldByName("Name"); ok {
    fmt.Println(fName.Type, fName.Name, fName.Tag)
}
 
if fId, ok := uType.FieldByName("Id"); ok {
    fmt.Println(fId.Type, fId.Name, fId.Tag)
}

실행 결과

string Name check:len(3,40)

int Id check:range(1,999999)

struct의 태그는 필드의 정합성 규칙이나 JSON/XML 변환을 위한 정보를 표현하는 용도로 자주 사용된다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.