Go言語(golang) 構造体のフィールド名、値、型を再帰的に列挙する
reflectパッケージを使ってループでフィールド名、値、型を出力する
package main import ( "fmt" "reflect" ) func main() { s := struct { String string Integer int Slice []int }{ String: "hello", Integer: 100, Slice: []int{10, 20, 30}, } rv := reflect.ValueOf(s) rt := rv.Type() // NumFieldでフィールド数を取得 for i := 0; i < rt.NumField(); i++ { field := rt.Field(i) kind := field.Type.Kind() // 型 value := rv.FieldByName(field.Name) // value は interface です。 fmt.Printf("name: %v, value %v, kind: %v\n", field.Name, value, kind) } // 実行結果 // name: String, value hello, kind: string // name: Integer, value 100, kind: int // name: Slice, value [10 20 30], kind: slice }
再帰的にフィールド名、値、型を出力する
package main import ( "fmt" "reflect" "strings" ) // reflect.Value を返す関数 func toReflectValue(i interface{}) (reflect.Value, bool) { rv, ok := i.(reflect.Value) if !ok { rv = reflect.ValueOf(i) } switch rv.Kind() { case reflect.Ptr: // ポインタ以外になるまで reflect.Indirect する return toReflectValue(reflect.Indirect(rv)) case reflect.Struct: return rv, true } // 構造体以外 return rv, false } func output(depth int, name string, value interface{}, kind reflect.Kind) { indent := strings.Repeat(" ", depth) if kind == reflect.Struct { fmt.Printf("%s- FieldName: %s, Type: %v\n", indent, name, kind) } else { fmt.Printf("%s- FieldName: %s, Value: %v, Type: %v\n", indent, name, value, kind) } } func recursive(depth int, rv reflect.Value) { typ := rv.Type() for i := 0; i < typ.NumField(); i++ { field := typ.Field(i) kind := field.Type.Kind() value := rv.FieldByName(field.Name) if kind == reflect.Ptr { vv, isStructure := toReflectValue(value) output(depth, field.Name, vv.Interface(), vv.Kind()) if isStructure { recursive(depth+1, vv) } } else { output(depth, field.Name, value, kind) if kind == reflect.Struct { recursive(depth+1, value) } } } } func main() { type User struct { Name string Age int } type Users struct { User1 *User User2 *User } s := struct { User *User Users *Users }{ User: &User{ Name: "Tanaka", Age: 31, }, Users: &Users{ &User{"Matsui", 45}, &User{"Suzuki", 46}, }, } rv, _ := toReflectValue(s) recursive(0, rv) // 実行結果 // - FieldName: User, Type: struct // - FieldName: Name, Value: Tanaka, Type: string // - FieldName: Age, Value: 31, Type: int // - FieldName: Users, Type: struct // - FieldName: User1, Type: struct // - FieldName: Name, Value: Matsui, Type: string // - FieldName: Age, Value: 45, Type: int // - FieldName: User2, Type: struct // - FieldName: Name, Value: Suzuki, Type: string // - FieldName: Age, Value: 46, Type: int }