Un tag per un campo consente di allegare meta-informazioni al campo che possono essere acquisite mediante la riflessione. Di solito viene utilizzato per fornire informazioni di trasformazione su come un campo struct viene codificato o decodificato da un altro formato (o archiviato / recuperato da un database), ma è possibile utilizzarlo per archiviare qualsiasi meta-informazione desiderata, sia destinata a un altro pacchetto o per uso personale.
Come menzionato nella documentazione di reflect.StructTag, per convenzione, il valore di una stringa tag è un elenco di key:"value"coppie separate da spazi , ad esempio:
type User struct {
Name string `json:"name" xml:"name"`
}
Di keysolito indica il pacchetto a cui fa riferimento il successivo "value", ad esempio le jsonchiavi vengono elaborate / utilizzate dal encoding/jsonpacchetto.
Se devono essere passate più informazioni in "value", di solito vengono specificate separandole con una virgola ( ','), ad es
Name string `json:"name,omitempty" xml:"name"`
Di solito un valore di trattino ( '-') per i "value"mezzi per escludere il campo dal processo (ad esempio, nel caso in cui jsonsignifichi non eseguire il marshalling o annullare il ripristino di quel campo).
Esempio di accesso ai tag personalizzati tramite reflection
Possiamo usare reflection ( reflectpacchetto) per accedere ai valori dei tag dei campi struct. Fondamentalmente dobbiamo acquisire la Typenostra struttura e quindi possiamo interrogare i campi, ad esempio con Type.Field(i int)o Type.FieldByName(name string). Questi metodi restituiscono un valore di StructFieldcui descrive / rappresenta un campo struct; ed StructField.Tagè un valore di tipo StructTagche descrive / rappresenta un valore di tag.
In precedenza abbiamo parlato di "convenzione" . Questo significa convenzione che se si seguono, si può usare il StructTag.Get(key string)metodo che analizza il valore di una variabile e restituisce la "value"del keyspecificato. La convenzione è implementata / integrata in questo Get()metodo. Se non segui la convenzione, Get()non sarai in grado di analizzare le key:"value"coppie e trovare quello che stai cercando. Anche questo non è un problema, ma è necessario implementare la propria logica di analisi.
Inoltre c'è StructTag.Lookup()( è stato aggiunto in Go 1.7) che è "simile Get()ma distingue il tag che non contiene la chiave data dal tag che associa una stringa vuota alla chiave data" .
Quindi vediamo un semplice esempio:
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"))
}
Output (provalo sul 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 ha presentato una presentazione sui tag struct chiamata:
I molti volti dei tag Struct (slide) (e un video )
Ecco un elenco di chiavi tag comunemente usate:
json - usato dal encoding/jsonpacchetto, dettagliato ajson.Marshal()
xml - usato dal encoding/xmlpacchetto, dettagliato axml.Marshal()
bson - usato da Gobson , dettagliato abson.Marshal()
protobuf - usato da github.com/golang/protobuf/proto, dettagliato nel pacchetto doc
yaml - usato dal gopkg.in/yaml.v2pacchetto, dettagliato ayaml.Marshal()
db - utilizzato dal github.com/jmoiron/sqlxpacchetto; utilizzato anche dal github.com/go-gorp/gorppacchetto
orm - usato dal github.com/astaxie/beego/ormpacchetto, dettagliato in Modelli - Beego ORM
gorm - usati dal github.com/jinzhu/gormpacchetto, alcuni esempi possono essere trovati nel loro documento: Modelli
valid - utilizzato dal github.com/asaskevich/govalidatorpacchetto, esempi sono disponibili nella pagina del progetto
datastore- utilizzato da appengine/datastore(piattaforma Google App Engine, servizio Datastore), dettagliato in Proprietà
schema - utilizzato da github.com/gorilla/schemaper compilare a structcon valori di modulo HTML, dettagliati nel documento del pacchetto
asn - utilizzato dal encoding/asn1pacchetto, dettagliato in asn1.Marshal()easn1.Unmarshal()
csv - utilizzato dal github.com/gocarina/gocsvpacchetto