feat(reflect): 添加结构体反射检查和字段操作功能

- 新增 inspectStructs 函数用于检查多个结构体类型
- 实现 inspectStructType递归检查结构体字段信息
- 添加 describeField 函数描述指定字段及其父级信息
- 新增 inspectTags 函数检查结构体标签信息
- 实现 getFieldValues 和 setFieldValues 操作结构体字段值
- 在 main.go 中调用新增的 main25、main26、main27 示例函数
- 扩展 types.go 中的结构体定义以支持新功能演示
This commit is contained in:
2025-11-01 21:08:14 +08:00
parent 3fe9c52e64
commit 4092ddd6d8
3 changed files with 153 additions and 1 deletions

View File

@@ -22,4 +22,7 @@ func main() {
main22()
main23()
main24()
main25()
main26()
main27()
}

View File

@@ -314,3 +314,141 @@ func main24() {
Printfln("Key: %v, Value: %v", key, val)
}
}
func inspectStructs(structs ...interface{}) {
for _, s := range structs {
structType := reflect.TypeOf(s)
if structType.Kind() == reflect.Struct {
inspectStructType("main", []int{}, structType, structType)
}
}
}
func inspectStructType(tag string, baseIndex []int, structType reflect.Type, baseType reflect.Type) {
Printfln("--- %v Struct Type: %v", tag, structType)
for i := 0; i < structType.NumField(); i++ {
fieldIndex := append(baseIndex, i)
field := structType.Field(i)
Printfln("%v - Field Base Index : %v , Field Index %v: Name:%v, Type:%v, Tag:%v , PkgPath:%v",
tag, fieldIndex, field.Index, field.Name, field.Type, field.Tag, field.PkgPath)
if field.Type.Kind() == reflect.Struct {
inspectStructType("field", fieldIndex, field.Type, baseType)
fieldWithFieldIndex := baseType.FieldByIndex(fieldIndex)
inspectStructType("fieldWithFieldIndex", fieldIndex, fieldWithFieldIndex.Type, baseType)
}
}
Printfln("--- End %v Struct Type: %v", tag, structType)
}
func describeField(s interface{}, fieldName string) {
Printfln("\ndescribeField:")
structType := reflect.TypeOf(s)
field, found := structType.FieldByName(fieldName)
if found {
Printfln("Top-Level Type: %v, Name: %v, Type: %v, Index: %v, Tag:%v , PkgPath:%v",
structType, field.Name, field.Type, field.Index, field.Tag, field.PkgPath)
index := field.Index
for len(index) > 1 {
index = index[0 : len(index)-1]
parentField := structType.FieldByIndex(index)
Printfln("Parent Name: %v, Type: %v, Index: %v, Tag:%v , PkgPath:%v",
parentField.Name, parentField.Type, parentField.Index, parentField.Tag, parentField.PkgPath)
}
} else {
Printfln("Field %v not found", fieldName)
}
}
func main25() {
Printfln("\nmain25:")
inspectStructs(Purchase{})
describeField(Purchase{}, "Price")
}
func inspectTags(s interface{}, tagName string) {
structType := reflect.TypeOf(s)
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
tag := field.Tag
valGet := tag.Get(tagName)
valLookup, ok := tag.Lookup(tagName)
Printfln("Field Name: %v, Type: %v, Tag: %v, TagName: %v, Get: %v, Lookup: %v, LookupOk: %v",
field.Name, field.Type, tag, tagName, valGet, valLookup, ok)
}
}
func main26() {
Printfln("\nmain26:")
inspectTags(Person{}, "alias")
stringType := reflect.TypeOf("")
structType := reflect.StructOf([]reflect.StructField{
{Name: "Name", Type: stringType, Tag: `alias:"id"`},
{Name: "City", Type: stringType, Tag: `alias:""`},
{Name: "Country", Type: stringType},
})
inspectTags(reflect.New(structType), "alias")
inspectTags(reflect.New(structType).Elem().Interface(), "alias")
}
func getFieldValues(s interface{}) {
structValue := reflect.ValueOf(s)
if structValue.Kind() != reflect.Struct {
Printfln("Not a struct")
return
}
for i := 0; i < structValue.NumField(); i++ {
fieldType := structValue.Type().Field(i)
fieldVal := structValue.Field(i)
Printfln("Name: %v, Type: %v, Value: %v", fieldType.Name, fieldType.Type, fieldVal)
}
}
func setFieldValues(s interface{}, newVals map[string]interface{}) {
structValue := reflect.ValueOf(s)
if structValue.Kind() != reflect.Ptr || structValue.Elem().Kind() != reflect.Struct {
Printfln("Not a pointer to a struct")
return
}
structValue = structValue.Elem()
for name, newValue := range newVals {
fieldVal := structValue.FieldByName(name)
if fieldVal.CanSet() {
fieldVal.Set(reflect.ValueOf(newValue))
} else if fieldVal.CanAddr() {
ptr := fieldVal.Addr()
if ptr.CanSet() {
ptr.Set(reflect.ValueOf(newValue))
} else {
Printfln("Can't set field via pointer: %v", name)
}
} else {
Printfln("Can't set field: %v", name)
}
}
}
func main27() {
Printfln("\nmain27:")
product := Product{Name: "Kayak", Category: "Watersports", Price: 279}
customer := Customer{Name: "Acme", City: "Chicago"}
Purchase := Purchase{Customer: customer, Product: product, Total: 279, taxRate: 10}
getFieldValues(Purchase)
Printfln("sets:")
setFieldValues(&Purchase, map[string]interface{}{
"City": "London",
"Category": "Boats",
"Total": 100.50,
})
getFieldValues(Purchase)
}

View File

@@ -14,9 +14,20 @@ type Payment struct {
Amount float64
}
type ProductPayment struct {
Payment `alias:"pay"`
}
type Purchase struct {
Product
Customer
Product
ProductPayment
Total float64
taxRate float64
}
type Person struct {
Name string `alias:"id"`
City string `alias:""`
Country string
}