Тег для поля позволяет вам прикрепить метаинформацию к полю, которую можно получить с помощью отражения. Обычно он используется для предоставления информации о преобразовании того, как поле структуры кодируется или декодируется из другого формата (или сохраняется / извлекается из базы данных), но вы можете использовать его для хранения любой мета-информации, которую вы хотите, либо предназначенной для другого пакет или для собственного использования.
Как упомянуто в документации 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пакет) для доступа к значениям тегов структурных полей. По сути, нам нужно получить 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", "bob@mycompany.com"}
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 провел презентацию о структурных тегах под названием:
Теги Многогранности Структуры (слайд) (и видео )
Вот список часто используемых ключей тегов:
json - используется в encoding/jsonпакете, подробно наjson.Marshal()
xml - используется в encoding/xmlпакете, подробно наxml.Marshal()
bson - используется Гобсоном , подробно наbson.Marshal()
protobuf - используется github.com/golang/protobuf/proto, подробно описано в пакете документов
yaml - используется в gopkg.in/yaml.v2пакете, подробно наyaml.Marshal()
db - используется в github.com/jmoiron/sqlxпакете; также используется github.com/go-gorp/gorpпакетом
orm - используется в github.com/astaxie/beego/ormпакете, подробно описано в Модели - Beego ORM
gorm - используемые github.com/jinzhu/gormпакетом, примеры можно найти в их документации: Модели
valid - используется github.com/asaskevich/govalidatorпакет, примеры можно найти на странице проекта
datastore- используется appengine/datastore(платформа Google App Engine, служба хранилища данных), подробно описано в разделе Свойства
schema - используется github.com/gorilla/schemaдля заполнения structзначений HTML формы, подробно описано в пакете документов
asn - используется в encoding/asn1пакете, подробно на asn1.Marshal()иasn1.Unmarshal()
csv - используется github.com/gocarina/gocsvпакетом