Ответ 1
Тег для поля позволяет вам привязать метаинформацию к полю, которое можно получить с помощью отражения. Обычно он используется для предоставления информации о преобразовании того, как поле структуры закодировано или декодировано из другого формата (или сохранено/получено из базы данных), но вы можете использовать его для хранения любой метаинформации, которую хотите, либо предназначенной для другой пакет или для вашего собственного использования.
Как упоминалось в документации 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
это означает, что он не должен маршалировать или отменять это поле).
Пример доступа к вашим пользовательским тэгам с использованием отражения
Мы можем использовать отражение (reflect
package) для доступа к значениям тега структурных полей. В принципе нам нужно получить Type
нашей структуры, а затем мы можем запросить поля, например. с Type.Field(i int)
или Type.FieldByName(name string)
. Эти методы возвращают значение StructField
, которые описывают/представляют поле структуры; и StructField.Tag
- это значение типа StructTag
, которое описывает/представляет значение тега.
Раньше мы говорили о "конвенции". Это соглашение означает, что если вы выполните его, вы можете использовать метод StructTag.Get(key string)
, который анализирует значение тега и возвращает "value"
из key
, который вы указываете. Соглашение реализовано/встроено в этот метод Get()
. Если вы не соблюдаете соглашение, Get()
не сможет проанализировать пары key:"value"
и найти то, что вы ищете. Это также не проблема, но тогда вам нужно реализовать свою собственную логику синтаксического анализа.
Также есть StructTag.Lookup()
(был добавлен в Go 1.7), который "как Get()
, но различает тег, не содержащий данный ключ из тега, связывающий пустую строку с заданным ключом".
Итак, посмотрим простой пример:
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 появилась презентация о тэгах struct, называемых:
Множество стилей тегов (слайд) (и видео)
Вот список широко используемых ключей тегов:
-
json
- используется пакетомencoding/json
, подробно описанным вjson.Marshal()
-
xml
- используется пакетомencoding/xml
, подробно описанным вxml.Marshal()
-
bson
- используется gobson, подробно описанный вbson.Marshal()
-
protobuf
- используетсяgithub.com/golang/protobuf/proto
, подробно описанный в пакете doc -
yaml
- используется пакетомgopkg.in/yaml.v2
, подробно описанным вyaml.Marshal()
-
db
- используетсяgithub.com/jmoiron/sqlx
; также используетсяgithub.com/go-gorp/gorp
package -
orm
- используется пакетомgithub.com/astaxie/beego/orm
, подробно описанным в Модели - Beego ORM -
gorm
- используетсяgithub.com/jinzhu/gorm
, примеры можно найти в их документе: Models -
valid
- используетсяgithub.com/asaskevich/govalidator
, примеры можно найти на странице проекта -
datastore
- используетсяappengine/datastore
(платформа Google App Engine, служба Datastore), подробно описанная в Properties -
schema
- используетсяgithub.com/gorilla/schema
для заполненияstruct
значениями формы HTML, подробно описанными в пакете doc -
asn
- используется пакетомencoding/asn1
, подробно описанным вasn1.Marshal()
иasn1.Unmarshal()