Uma tag para um campo permite anexar meta-informações ao campo que pode ser adquirido usando reflexão. Geralmente, ele é usado para fornecer informações de transformação sobre como um campo de estrutura é codificado ou decodificado de outro formato (ou armazenado / recuperado de um banco de dados), mas você pode usá-lo para armazenar qualquer meta-informação que desejar, destinada a outra pacote ou para seu próprio uso.
Conforme mencionado na documentação de reflect.StructTag
, por convenção, o valor de uma sequência de tags é uma lista de key:"value"
pares separados por espaço , por exemplo:
type User struct {
Name string `json:"name" xml:"name"`
}
O key
normalmente indica o pacote que o subsequente "value"
é de, por exemplo, json
as teclas são processados / utilizado pelo encoding/json
pacote.
Se várias informações devem ser passadas no "value"
, normalmente elas são especificadas separando-as com uma vírgula ( ','
), por exemplo
Name string `json:"name,omitempty" xml:"name"`
Geralmente, um valor de hífen ( '-'
) para os "value"
meios de excluir o campo do processo (por exemplo, no caso de json
isso significar não empacotar ou descompactar esse campo).
Exemplo de acesso às suas tags personalizadas usando reflexão
Podemos usar a reflexão ( reflect
pacote) para acessar os valores das tags dos campos struct. Basicamente, precisamos adquirir Type
nossa estrutura e, em seguida, podemos consultar os campos, por exemplo, com Type.Field(i int)
ou Type.FieldByName(name string)
. Esses métodos retornam um valor StructField
que descreve / representa um campo struct; e StructField.Tag
é um valor do tipo StructTag
que descreve / representa um valor de tag.
Anteriormente, conversamos sobre "convenção" . Essa convenção significa que, se você a seguir, poderá usar o StructTag.Get(key string)
método que analisa o valor de uma tag e retorna "value"
o que key
você especificar. A convenção é implementada / incorporada a este Get()
método. Se você não seguir a convenção, Get()
não poderá analisar key:"value"
pares e encontrar o que está procurando. Isso também não é um problema, mas você precisa implementar sua própria lógica de análise.
Também existe StructTag.Lookup()
(foi adicionado no Go 1.7) que é "semelhante, Get()
mas distingue, a marca que não contém a chave especificada da marca que associa uma cadeia vazia à chave especificada" .
Então, vamos ver um exemplo simples:
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"))
}
Saída (experimente no 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"
O GopherCon 2015 teve uma apresentação sobre tags struct chamada:
As muitas faces das tags Struct (slide) (e um vídeo )
Aqui está uma lista das chaves de tag mais usadas:
json
- usado pela encoding/json
embalagem, detalhado emjson.Marshal()
xml
- usado pela encoding/xml
embalagem, detalhado emxml.Marshal()
bson
- usado por gobson , detalhado embson.Marshal()
protobuf
- usado por github.com/golang/protobuf/proto
, detalhado no pacote doc
yaml
- usado pela gopkg.in/yaml.v2
embalagem, detalhado emyaml.Marshal()
db
- usado pela github.com/jmoiron/sqlx
embalagem; também usado pelo github.com/go-gorp/gorp
pacote
orm
- usado pelo github.com/astaxie/beego/orm
pacote, detalhado em Modelos - Beego ORM
gorm
- usado pelo github.com/jinzhu/gorm
pacote, exemplos podem ser encontrados em seus documentos: Modelos
valid
- usado pelo github.com/asaskevich/govalidator
pacote, exemplos podem ser encontrados na página do projeto
datastore
- usado por appengine/datastore
(plataforma Google App Engine, serviço Datastore), detalhado em Propriedades
schema
- usado por github.com/gorilla/schema
para preencher um struct
com valores de formulário HTML, detalhados no documento do pacote
asn
- usado pela encoding/asn1
embalagem, detalhado em asn1.Marshal()
easn1.Unmarshal()
csv
- usado pela github.com/gocarina/gocsv
embalagem