如何在使用反射时设置标签.新增功能



从现有结构创建新结构时,不会在新结构上设置标记。

例如:

package main
import (
"fmt"
"reflect"
)
type Foo struct {
Bar string `custom:"tag"`
}
func readTag(e interface{}) {
t := reflect.TypeOf(e).Elem()
f, _ := t.FieldByName("Bar")
fmt.Println(f.Tag)
}
func main() {
foo := &Foo{"baz"}
fmt.Println(foo)
readTag(foo)
fooType := reflect.TypeOf(foo).Elem()
newFoo := reflect.New(fooType).Elem()
newFoo.FieldByName("Bar").SetString("baz2")
fmt.Println(newFoo)
readTag(&newFoo)// empty
}

游乐场链接: https://play.golang.org/p/7-zMPnwQ8Vo

使用reflect.New时如何设置标签?甚至可能吗?

标签不属于实例,标签属于类型。

因此,当您创建类型的新实例时,它们的类型将是相同的"佩戴"相同的标记。是使用文本还是通过reflect包创建新实例并不重要。

你的情况下的问题是newFooreflect.Value类型,而&newFoo*reflect.Value类型,它不是指向你的结构的指针(不是*Foo类型(。

如果解开结构值的包装:

newFoo.Interface()

你传递这个,你把Elem()调用设置为可选(只当它是一个指针时才这样做(:

func readTag(e interface{}) {
t := reflect.TypeOf(e)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
f, _ := t.FieldByName("Bar")
fmt.Println(f.Tag)
}

然后你会得到相同的标签(在Go Playground上尝试(:

&{baz}
custom:"tag"
{baz2}
custom:"tag"

如果保持reflect.Value包装结构指针并从中解包,则会得到相同的结果:

newFooPtr := reflect.New(fooType)
newFoo := newFooPtr.Elem()
newFoo.FieldByName("Bar").SetString("baz2")
fmt.Println(newFoo)
readTag(newFooPtr.Interface()) // empty

然后readTag()不需要修改。在Go Playground上尝试此版本。

最新更新