feat(reflect): 添加结构体反射检查和字段操作功能
- 新增 inspectStructs 函数用于检查多个结构体类型 - 实现 inspectStructType递归检查结构体字段信息 - 添加 describeField 函数描述指定字段及其父级信息 - 新增 inspectTags 函数检查结构体标签信息 - 实现 getFieldValues 和 setFieldValues 操作结构体字段值 - 在 main.go 中调用新增的 main25、main26、main27 示例函数 - 扩展 types.go 中的结构体定义以支持新功能演示
This commit is contained in:
@@ -22,4 +22,7 @@ func main() {
|
||||
main22()
|
||||
main23()
|
||||
main24()
|
||||
main25()
|
||||
main26()
|
||||
main27()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user