gpt4 book ai didi

go - 使用反射从深度嵌套的结构中提取标签

转载 作者:行者123 更新时间:2023-12-01 22:17:00 25 4
gpt4 key购买 nike

我正在尝试从一些深层嵌套的结构中提取一些标签。这些结构是从protobuf消息生成的,并且包含json标签。

我有一个指向结构的指针,该结构可能包含一个结构,该结构包含我可能想要其标签的字段。我可以使用类型进行迭代以获取结构的字段,但是当我遇到一个指针字段时,如何获取其值然后递归?

// Struct has hierarchy like this 
a := &somepb.UpdateRequest{
Updates: []*somepb.UpdateRequest_Foo{
&somepb.UpdateRequest_Foo{
Id: 1,
Foo: &somepb.FooInfo{
Metadata: &somepb.Metadata{
Name: "Foo",
Description: "Bar",
},
Some: "s",
Things: "o",
Are: "m",
Broken: "e",
Here: "p",
},
},
},
}

// ParseStruct parses struct tags of given object
func ParseStruct(obj interface{}, tag string) {
r := reflect.ValueOf(obj)
if r.Kind() == reflect.Ptr {
obj = r.Elem().Interface()
}
rv := reflect.TypeOf(obj)
for i := 0; i < rv.NumField(); i++ {
f := rv.Field(i)
// This is to avoid getting tags for Metadata itself (from the struct above)
// which is *Metadata, I want the tags for Name and Description
// inside *Metadata instead
if f.Type.Kind() == reflect.Ptr {
value := f.Tag.Get(tag)
if len(value) == 0 {
continue
}
fmt.Println(value)
}
}
}

最佳答案

reflect.Typereflect.Value都有Elem()方法。根据document
ElemType方法。

// Elem returns a type's element type.
// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
Elem() Type
Value.Elem:
func (v Value) Elem() Value

Elem returns the value that the interface v contains or that the pointer v points to. It panics if v's Kind is not Interface or Ptr. It returns the zero Value if v is nil.

您可以使用 Elem()方法获取指针的内容,然后使用该内容进行递归。但是,鉴于您的原始API是 func(interface{},string),您需要使用 Value.Elem().Interface()来获取有意义的 interface{}。但是,相反,我建议您更改API以接受 reflect.Type-因为这对于标记提取最为清楚。

示例代码:
func ParseStruct(t reflect.Type, tag string) {
if t.Kind() == reflect.Ptr {
t = t.Elm()
}
if t.Kind() != reflect.Struct {
return
}

for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
value := f.Tag.Get(tag)
ft := t.Type
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}

// It seems that you don't want a tag from an struct field; only other fields' tags are needed
if ft.Kind() != reflect.Struct {
if len(value) != 0 {
fmt.Println(value)
}
continue
}

ParseStruct(ft,tag)
}
}

请注意,此代码非常简单-它不会处理 slice 或 map 中的结构标签。

关于go - 使用反射从深度嵌套的结构中提取标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59014705/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com