プログラム実行中に、動的に型の情報などを判別する技術( リフレクション(reflection)
)について確認します。Goでは、reflectパッケージを利用して実現できます。利用機会は少ないですし、必要なければ利用しないほうが良い機能ですが、簡単に概要だけ確認します。
目次
reflect.Value型の値を取得
reflect.ValueOf関数
で reflect.Value型の値
を取得します。
その後、reflect.Value
の Kindメソッド
で型情報を確認します。
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Age int
}
func test(i interface{}) {
// reflect.Value型の値を取得
v := reflect.ValueOf(i)
fmt.Printf("v.Kind()=%v\n\n", v.Kind())
}
func main() {
fmt.Println("int")
test(100)
fmt.Println("string")
test("hello")
fmt.Println("slice")
test([]int{1, 2, 3, 4, 5, 6, 7, 8})
fmt.Println("map")
test(map[string]int{"aa": 111, "bb": 222})
fmt.Println("struct")
test(User{"yamada", 27})
fmt.Println("ptr")
i := 100
test(&i)
}
int
v.Kind()=int
string
v.Kind()=string
slice
v.Kind()=slice
map
v.Kind()=map
struct
v.Kind()=struct
ptr
v.Kind()=ptr
reflect.Type型のメソッド
( 型ごとに利用できるメソッドが異なる )
reflect.Value
の Typeメソッド
で reflect.Type型の値
を取得します。reflect.Type型
で利用できるメソッドは、型ごとに異なります。
以下例で利用している NumFieldメソッド
Fieldメソッド
は struct
以外で利用すると panic
となります。
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string "xxx"
Age int "yyy"
}
func test(i interface{}) {
// reflect.Value型の値を取得
v := reflect.ValueOf(i)
fmt.Printf("v.Kind()=%v\n\n", v.Kind())
if v.Kind() == reflect.Struct {
// reflect.Type型の値を取得
t := v.Type()
for i := 0; i < t.NumField(); i++ {
sf := t.Field(i)
fmt.Printf("sf.Index=%v\n", sf.Index)
fmt.Printf("sf.Name=%v\n", sf.Name)
fmt.Printf("sf.Type=%v\n", sf.Type)
fmt.Printf("sf.Tag=%v\n", sf.Tag)
}
}
}
func main() {
fmt.Println("struct")
test(User{"yamada", 27})
}
struct
v.Kind()=struct
sf.Index=[0]
sf.Name=Name
sf.Type=string
sf.Tag=xxx
sf.Index=[1]
sf.Name=Age
sf.Type=int
sf.Tag=yyy