Znacznik pola umożliwia dołączenie do pola meta-informacji, które można uzyskać za pomocą odbicia. Zwykle służy do dostarczania informacji o transformacji, w jaki sposób pole struct jest kodowane lub dekodowane z innego formatu (lub przechowywane / pobierane z bazy danych), ale możesz go użyć do przechowywania dowolnych meta-informacji, które chcesz, albo przeznaczonych dla innego pakiet lub na własny użytek.
Jak wspomniano w dokumentacji reflect.StructTag, zgodnie z konwencją wartość ciągu znacznika jest oddzieloną spacją listą key:"value"par, na przykład:
type User struct {
Name string `json:"name" xml:"name"`
}
keyZwykle oznacza pakietu, który następnie "value"jest, na przykład, jsonklucze są przetwarzane / wykorzystywane przezencoding/json pakiet.
Jeśli ma zostać przekazanych wiele informacji "value", zwykle określa się je, oddzielając je przecinkiem ( ','), np
Name string `json:"name,omitempty" xml:"name"`
Zwykle wartość myślnika ( '-') dla "value"sposobu wykluczenia pola z procesu (np. W przypadkujson gdy oznacza to nie marszrowanie lub odmarszowanie tego pola).
Przykład uzyskiwania dostępu do niestandardowych tagów za pomocą odbicia
Możemy użyć refleksji ( reflectpakietu), aby uzyskać dostęp do wartości znaczników pól struct. Zasadniczo musimy zdobyć Typenaszą strukturę, a następnie możemy wyszukiwać pola np. Za pomocą Type.Field(i int)lub Type.FieldByName(name string). Te metody zwracają wartość, StructFieldktóra opisuje / reprezentuje pole struct; i StructField.Tagjest wartością typuStructTag która opisuje / reprezentuje wartość znacznika.
Wcześniej rozmawialiśmy o „konwencji” . Ta konwencja oznacza, że jeśli będziesz go przestrzegać, możesz użyć StructTag.Get(key string)metody, która analizuje wartość znacznika i zwraca ci określoną "value"przez keyCiebie wartość. Konwencja jest realizowany / wbudowana w tej Get()metodzie. Jeśli nie zastosujesz się do konwencji, Get()nie będziesz mógł przeanalizowaćkey:"value" par i znaleźć tego, czego szukasz. To też nie jest problem, ale musisz zaimplementować własną logikę parsowania.
Jest też StructTag.Lookup()(został dodany w wersji 1.7), który jest „podobny, Get()ale odróżnia znacznik niezawierający danego klucza od znacznika kojarzącego pusty ciąg z danym kluczem” .
Zobaczmy więc prosty przykład:
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"))
}
Wyjście (wypróbuj na 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 miał prezentację na temat tagów struktur o nazwie:
The Many Faces of Struct Tags (slajd) (i wideo )
Oto lista najczęściej używanych kluczy tagów:
json - używane przez encoding/jsonpaczkę, wyszczególnione najson.Marshal()
xml - używane przez encoding/xmlpaczkę, wyszczególnione naxml.Marshal()
bson - używane przez gobsona , wyszczególnione nabson.Marshal()
protobuf - używane przez github.com/golang/protobuf/proto, wyszczególnione w pakiecie doc
yaml - używane przez gopkg.in/yaml.v2paczkę, wyszczególnione nayaml.Marshal()
db - używane przez github.com/jmoiron/sqlxpaczkę; używany również przez github.com/go-gorp/gorppakiet
orm - używane przez github.com/astaxie/beego/ormpakiet, wyszczególnione w Models - Beego ORM
gorm - używane przez github.com/jinzhu/gormpakiet, przykłady można znaleźć w ich doc: Models
valid - używane przez github.com/asaskevich/govalidatorpakiet, przykłady można znaleźć na stronie projektu
datastore- używane przez appengine/datastore(platforma Google App Engine, usługa magazynu danych), wyszczególnione w oknie Właściwości
schema - używane przez github.com/gorilla/schemado wypełnienia structwartości formularza HTML, wyszczególnionych w dokumencie pakietu
asn - używane przez encoding/asn1opakowanie, wyszczególnione na asn1.Marshal()iasn1.Unmarshal()
csv - używane przez github.com/gocarina/gocsvpaczkę