1

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

例如:

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?甚至可能吗?

4

1 回答 1

4

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

因此,当您创建类型的新实例时,它们的类型将是相同的“佩戴”相同的标签。reflect使用文字或通过包创建新实例都没有关系。

您的问题newFoo是 type reflect.Value,并且&newFoo是 type *reflect.Value,它不是指向您的 struct 的指针(不是 type *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上试试这个版本。

于 2020-02-17T10:30:29.260 回答