Reflection Basics
Struct Tags
Struct tags attach metadata that libraries can read through reflection.
struct tags
Tags are strings attached to fields. Reflection can read them so encoders and validators can follow naming rules.
Struct Tags
struct_tags_reflect.go
Replay: real traced execution (multi-file project)
package main
import (
"fmt"
"reflect"
)
type Item struct {
SKU string `json:"sku"`
Count int `json:"count"`
}
func main() {
var fieldIndex = 0
itemType := reflect.TypeOf(Item{})
field := itemType.Field(fieldIndex)
jsonName := field.Tag.Get("json")
fmt.Println("field_index=", fieldIndex)
fmt.Println("field_name=", field.Name)
fmt.Println("field_type=", field.Type.String())
fmt.Println("json_name=", jsonName)
}
package main
import (
"fmt"
"reflect"
)
type Item struct {
SKU string `json:"sku"`
Count int `json:"count"`
}
func main() {
var fieldIndex = 1
itemType := reflect.TypeOf(Item{})
field := itemType.Field(fieldIndex)
jsonName := field.Tag.Get("json")
fmt.Println("field_index=", fieldIndex)
fmt.Println("field_name=", field.Name)
fmt.Println("field_type=", field.Type.String())
fmt.Println("json_name=", jsonName)
}
fieldIndex ← 0, itemType ← &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:6798, PtrToThis:19168}}
13func main() {14 var fieldIndex→ 0 = 0 //@fieldIndex=115 itemType→ &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:6798, PtrToThis:19168}} := reflect.TypeOf(Item{})16 field→ reflect.StructField{Name:"SKU", PkgPath:"", Type:(*reflect.rtype)(⟨addr D⟩), Tag:"json:\"sku\"", Offset:0x0, Index:[]int{0}, Anonymous:false} := itemType&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:6798, PtrToThis:19168}}.Field(fieldIndex0)17 jsonName→ "sku" := field.Tag"json:\"sku\"".Get("json")1819 fmt.Println("field_index=", fieldIndex0)20 fmt.Println("field_name=", field.Name"SKU")21 fmt.Println("field_type=", field.Type&reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr E⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x18, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr F⟩), GCData:(*uint8)(⟨addr C⟩), Str:3757, PtrToThis:20064}}.String())22 fmt.Println("json_name=", jsonName"sku")23}outputfield_index= 0 field_name= SKU field_type= string json_name= sku
fieldIndex ← 1, itemType ← &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:6798, PtrToThis:19168}}
13func main() {14 var fieldIndex→ 1 = 115 itemType→ &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:6798, PtrToThis:19168}} := reflect.TypeOf(Item{})16 field→ reflect.StructField{Name:"Count", PkgPath:"", Type:(*reflect.rtype)(⟨addr D⟩), Tag:"json:\"count\"", Offset:0x10, Index:[]int{1}, Anonymous:false} := itemType&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:6798, PtrToThis:19168}}.Field(fieldIndex1)17 jsonName→ "count" := field.Tag"json:\"count\"".Get("json")1819 fmt.Println("field_index=", fieldIndex1)20 fmt.Println("field_name=", field.Name"Count")21 fmt.Println("field_type=", field.Type&reflect.rtype{t:abi.Type{Size_:0x8, PtrBytes:0x0, Hash:⟨addr E⟩, TFlag:0xf, Align_:0x8, FieldAlign_:0x8, Kind_:0x2, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr F⟩), GCData:(*uint8)(⟨addr G⟩), Str:814, PtrToThis:20640}}.String())22 fmt.Println("json_name=", jsonName"count")23}outputfield_index= 1 field_name= Count field_type= int json_name= count