Вопрос по struct, reflection, go – Как использовать теги в Go?

313

вПерейти спецификация языкаВ нем упоминается краткий обзор тегов:

A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration. The tags are made visible through a reflection interface but are otherwise ignored.

// A struct corresponding to the TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers.
struct {
  microsec  uint64 "field 1"
  serverIP6 uint64 "field 2"
  process   string "field 3"
}

Это очень короткое объяснение IMO, и мне было интересно, если кто-нибудь может предоставить мне, как будут использоваться эти теги?

Исправление этой ссылки должно бытьstackoverflow.com/q/53487371/1569204 Bruce Adams
У меня есть связанный вопрос по использованию «семантики»; Комментарии:stackoverflow.com/questions/53101458/… Bruce Adams

Ваш Ответ

2   ответа
144

Вот очень простой пример использования тегов сencoding/json пакет для управления интерпретацией полей во время кодирования и декодирования:

Попробуй вживую:http://play.golang.org/p/BMeR8p1cKf

package main

import (
    "fmt"
    "encoding/json"
)

type Person struct {
    FirstName  string `json:"first_name"`
    LastName   string `json:"last_name"`
    MiddleName string `json:"middle_name,omitempty"`
}

func main() {
    json_string := `
    {
        "first_name": "John",
        "last_name": "Smith"
    }`

    person := new(Person)
    json.Unmarshal([]byte(json_string), person)
    fmt.Println(person)

    new_json, _ := json.Marshal(person)
    fmt.Printf("%s\n", new_json)
}

// *Output*
// &{John Smith }
// {"first_name":"John","last_name":"Smith"}

Пакет json может посмотреть на теги для поля и узнать, как отобразить json & lt; = & gt; struct field, а также дополнительные параметры, например, следует ли игнорировать пустые поля при сериализации обратно в json.

По сути, любой пакет может использовать отражение в полях для просмотра значений тегов и воздействия на эти значения. Немного больше информации о них в пакете отражают
http://golang.org/pkg/reflect/#StructTag :

By convention, tag strings are a concatenation of optionally space-separated key:"value" pairs. Each key is a non-empty string consisting of non-control characters other than space (U+0020 ' '), quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted using U+0022 '"' characters and Go string literal syntax.

@isbadawi: я не Java-парень, но с первого взгляда на определение Java-аннотаций, да, похоже, они достигают одной и той же цели; прикрепление метаданных к элементам, которые могут быть проверены во время выполнения.
Вроде как аннотации Java?
Как часть драйвера MongoDB для Go, mgo также использует теги в своем пакете bson (который также может использоваться сам по себе). Это дает вам точный контроль над тем, что генерируется BSON. Увидетьgodoc.org/labix.org/v2/mgo/bson#pkg-files
Не совсем Java-аннотации. Java-аннотации безопасны по типу и проверяются временем компиляции, а не строковыми литералами, такими как go. Java-аннотации гораздо более мощные и надежные, чем базовые положения о метаданных golang.
FWIW то же самое можно сделать для XML в Go тоже.
475

Тег для поля позволяет вам прикрепить метаинформацию к полю, которую можно получить с помощью отражения. Обычно он используется для предоставления информации о преобразовании того, как структурное поле кодируется или декодируется из другого формата (или сохраняется / извлекается из базы данных), но вы можете использовать его для хранения любой мета-информации, которую вы хотите, либо предназначенной для другого пакет или для собственного использования.

Как указано в документацииreflect.StructTagпо соглашению значение строки тега - это список разделенных пробеламиkey:"value" пары, например:

type User struct {
    Name string `json:"name" xml:"name"`
}

key обычно обозначает пакет, который последующий"value" для, например,json ключи обрабатываются / используютсяencoding/json пакет.

Если многократная информация должна быть передана в"value"обычно указывается через запятую (','), например

Name string `json:"name,omitempty" xml:"name"`

Обычно значение тире ('-') для"value" означает исключить поле из процесса (например, в случаеjson это означает не маршалировать и не демаршировать это поле).

Example of accessing your custom tags using reflection

Мы можем использовать отражение (reflect пакет) для доступа к значениям тегов структурных полей. В основном нам нужно приобрестиType нашей структуры, а затем мы можем запросить поля, например, сType.Field(i int) или жеType.FieldByName(name string), Эти методы возвращают значениеStructField который описывает / представляет поле структуры; а такжеStructField.Tag это значение типаStructTag который описывает / представляет значение тега.

Ранее мы говорили о"convention", Это соглашение означает, что если вы будете следовать ему, вы можете использоватьStructTag.Get(key string) метод, который анализирует значение тега и возвращает вам"value" изkey Вы указываете.convention реализован / встроен в этоGet() метод. Если вы не соблюдаете соглашение,Get() не сможет разобратьkey:"value" пары и найти то, что вы ищете. Это также не проблема, но тогда вам нужно реализовать свою собственную логику синтаксического анализа.

Также естьStructTag.Lookup() (был добавлен в Go 1.7), который"like Get() but distinguishes the tag not containing the given key from the tag associating an empty string with the given key".

Итак, давайте посмотрим на простой пример:

type User struct {
    Name  string `mytag:"MyName"`
    Email string `mytag:"MyEmail"`
}

u := User{"Bob", "[email protected]"}
t := reflect.TypeOf(u)

for _, fieldName := range []string{"Name", "Email"} {
    field, found := t.FieldByName(fieldName)
    if !found {
        continue
    }
    fmt.Printf("\nField: User.%s\n", fieldName)
    fmt.Printf("\tWhole tag value : %q\n", field.Tag)
    fmt.Printf("\tValue of 'mytag': %q\n", field.Tag.Get("mytag"))
}

Вывод (попробуйте наGo Playground):

Field: User.Name
    Whole tag value : "mytag:\"MyName\""
    Value of 'mytag': "MyName"

Field: User.Email
    Whole tag value : "mytag:\"MyEmail\""
    Value of 'mytag': "MyEmail"

GopherCon 2015 провел презентацию о структурных тегах под названием:

Теги Многогранности Структуры (слайд) (ивидео)

Here is a list of commonly used tag keys:

очень хорошее резюме!
Отличный ответ! Спасибо!
Отлично сработано ! Оценил
Отличный ответ. Здесь гораздо больше полезной информации, чем в той, которая в десять раз превышает эту карму.
Какой отличный ответ

Похожие вопросы