Какая польза для тегов в Go?

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

За объявлением поля может следовать необязательный тег строкового литерала, который становится атрибутом для всех полей соответствующего объявления поля. Теги становятся видимыми через интерфейс отражения, но в противном случае игнорируются.

// 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" } 

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

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

Как упоминалось в документации reflect.StructTag , по соглашению значение строки тега представляет собой список key:"value" разделенных пробелами key:"value" пары 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 это означает не маршалировать или не разлагать это поле).

Пример доступа к вашим пользовательским тэгам с использованием отражения

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

Раньше мы говорили о «конвенции» . Это соглашение означает, что если вы будете следовать ему, вы можете использовать метод StructTag.Get(key string) который анализирует значение тега и возвращает вам "value" указанного вами key . Конвенция реализована / встроена в этот метод Get() . Если вы не соблюдаете соглашение, Get() не сможет проанализировать key:"value" пары 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 ):

 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 – используется 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
  • orm – используется пакетом github.com/astaxie/beego/orm , подробно представленном на моделях – Beego ORM
  • gorm – используется пакетом github.com/jinzhu/gorm , примеры можно найти в их документе: Модели
  • valid – используется пакетом github.com/asaskevich/govalidator , примеры можно найти на странице проекта
  • datastore – используется appengine/datastore (платформа Google App Engine, служба Datastore), подробная информация о свойствах
  • schema – используется github.com/gorilla/schema для заполнения struct с помощью значений формы HTML, подробно описанных в пакете doc
  • asn – используется пакетом encoding/asn1 , подробно описанным в asn1.Marshal() и asn1.Unmarshal()
  • csv – используется пакетом github.com/gocarina/gocsv

Вот очень простой пример использования тегов с пакетом 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 может посмотреть на tags для поля и узнать, как сопоставить json <=> поле struct, а также дополнительные параметры, например, следует ли игнорировать пустые поля при сериализации обратно в json.

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

По соглашению строки тегов представляют собой конкатенацию опционально разделенных пробелами ключей: пары «значение». Каждый ключ представляет собой непустую строку, состоящую из неконтролируемых символов, отличных от пробела (U + 0020 ”), цитаты (U + 0022 ‘”‘) и двоеточия (U + 003A ‘:’). Каждое значение цитируется используя символы U + 0022 ” ‘и Go string literal.

  • Нечитаемая только альтернатива анонимным типам
  • Каковы различия между структурой и classом в C ++?
  • C Typedef и Struct Question
  • Как определить структуру typedef, содержащую указатели на себя?
  • C инициализировать массив внутри структуры
  • Почему размер sizeof для структуры не равен сумме sizeof каждого члена?
  • Класс смешивания и структура
  • Назначить одну структуру другому в C
  • Как работает встроенная реализация ValueType.GetHashCode?
  • Как правильно назначить новое строковое значение?
  • typedef struct vs struct definitions
  • Давайте будем гением компьютера.