Как установить теги при использовании отражения. Новое - PullRequest
1 голос
/ 17 февраля 2020

При создании новой структуры из существующей структуры теги в новой структуре не устанавливаются.

Например:

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? Это вообще возможно?

1 Ответ

4 голосов
/ 17 февраля 2020

Теги не принадлежат экземплярам, ​​теги принадлежат типам.

Таким образом, когда вы создаете новые экземпляры вашего типа, их тип будет одинаково «носить» одинаковые теги. Не имеет значения, создаете ли вы новые экземпляры с литералами или через пакет reflect.

Проблема в вашем случае состоит в том, что newFoo имеет тип reflect.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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...