Reflection Basics
Struct Fields
Reflection can enumerate a struct type's fields and names.
struct fields
Use field metadata when a framework or helper needs to inspect the shape of a struct.
Struct Fields
struct_fields.go
Replay: real traced execution (multi-file project)
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Level int
}
func main() {
var level = 3
user := User{Name: "Ada", Level: level}
userType := reflect.TypeOf(user)
firstField := userType.Field(0)
secondField := userType.Field(1)
fmt.Println("level=", level)
fmt.Println("type=", userType.Name())
fmt.Println("field_count=", userType.NumField())
fmt.Println("first_field=", firstField.Name)
fmt.Println("second_type=", secondField.Type.String())
}
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Level int
}
func main() {
var level = 1
user := User{Name: "Ada", Level: level}
userType := reflect.TypeOf(user)
firstField := userType.Field(0)
secondField := userType.Field(1)
fmt.Println("level=", level)
fmt.Println("type=", userType.Name())
fmt.Println("field_count=", userType.NumField())
fmt.Println("first_field=", firstField.Name)
fmt.Println("second_type=", secondField.Type.String())
}
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Level int
}
func main() {
var level = 5
user := User{Name: "Ada", Level: level}
userType := reflect.TypeOf(user)
firstField := userType.Field(0)
secondField := userType.Field(1)
fmt.Println("level=", level)
fmt.Println("type=", userType.Name())
fmt.Println("field_count=", userType.NumField())
fmt.Println("first_field=", firstField.Name)
fmt.Println("second_type=", secondField.Type.String())
}
level ← 3, user ← main.User{Name:"Ada", Level:3}, userType ← &reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}
13func main() {14 var level→ 3 = 3 //@level=1, 515 user→ main.User{Name:"Ada", Level:3} := User{Name: "Ada", Level: level3}16 userType→ &reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}} := reflect.TypeOf(usermain.User{Name:"Ada", Level:3})17 firstField→ reflect.StructField{Name:"Name", PkgPath:"", Type:(*reflect.rtype)(⟨addr D⟩), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false} := userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Field(0)18 secondField→ reflect.StructField{Name:"Level", PkgPath:"", Type:(*reflect.rtype)(⟨addr E⟩), Tag:"", Offset:0x10, Index:[]int{1}, Anonymous:false} := userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Field(1)1920 fmt.Println("level=", level3)21 fmt.Println("type=", userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Name())22 fmt.Println("field_count=", userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.NumField())23 fmt.Println("first_field=", firstField.Name"Name")24 fmt.Println("second_type=", secondField.Type&reflect.rtype{t:abi.Type{Size_:0x8, PtrBytes:0x0, Hash:⟨addr F⟩, TFlag:0xf, Align_:0x8, FieldAlign_:0x8, Kind_:0x2, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr G⟩), GCData:(*uint8)(⟨addr H⟩), Str:814, PtrToThis:20608}}.String())25}outputlevel= 3 type= User field_count= 2 first_field= Name second_type= int
level ← 1, user ← main.User{Name:"Ada", Level:1}, userType ← &reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}
13func main() {14 var level→ 1 = 115 user→ main.User{Name:"Ada", Level:1} := User{Name: "Ada", Level: level1}16 userType→ &reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}} := reflect.TypeOf(usermain.User{Name:"Ada", Level:1})17 firstField→ reflect.StructField{Name:"Name", PkgPath:"", Type:(*reflect.rtype)(⟨addr D⟩), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false} := userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Field(0)18 secondField→ reflect.StructField{Name:"Level", PkgPath:"", Type:(*reflect.rtype)(⟨addr E⟩), Tag:"", Offset:0x10, Index:[]int{1}, Anonymous:false} := userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Field(1)1920 fmt.Println("level=", level1)21 fmt.Println("type=", userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Name())22 fmt.Println("field_count=", userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.NumField())23 fmt.Println("first_field=", firstField.Name"Name")24 fmt.Println("second_type=", secondField.Type&reflect.rtype{t:abi.Type{Size_:0x8, PtrBytes:0x0, Hash:⟨addr F⟩, TFlag:0xf, Align_:0x8, FieldAlign_:0x8, Kind_:0x2, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr G⟩), GCData:(*uint8)(⟨addr H⟩), Str:814, PtrToThis:20608}}.String())25}outputlevel= 1 type= User field_count= 2 first_field= Name second_type= int
level ← 5, user ← main.User{Name:"Ada", Level:5}, userType ← &reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}
13func main() {14 var level→ 5 = 515 user→ main.User{Name:"Ada", Level:5} := User{Name: "Ada", Level: level5}16 userType→ &reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}} := reflect.TypeOf(usermain.User{Name:"Ada", Level:5})17 firstField→ reflect.StructField{Name:"Name", PkgPath:"", Type:(*reflect.rtype)(⟨addr D⟩), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false} := userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Field(0)18 secondField→ reflect.StructField{Name:"Level", PkgPath:"", Type:(*reflect.rtype)(⟨addr E⟩), Tag:"", Offset:0x10, Index:[]int{1}, Anonymous:false} := userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Field(1)1920 fmt.Println("level=", level5)21 fmt.Println("type=", userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.Name())22 fmt.Println("field_count=", userType&reflect.rtype{t:abi.Type{Size_:0x18, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:6806, PtrToThis:19136}}.NumField())23 fmt.Println("first_field=", firstField.Name"Name")24 fmt.Println("second_type=", secondField.Type&reflect.rtype{t:abi.Type{Size_:0x8, PtrBytes:0x0, Hash:⟨addr F⟩, TFlag:0xf, Align_:0x8, FieldAlign_:0x8, Kind_:0x2, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr G⟩), GCData:(*uint8)(⟨addr H⟩), Str:814, PtrToThis:20608}}.String())25}outputlevel= 5 type= User field_count= 2 first_field= Name second_type= int