Jakie są zastosowania tagów w Go?
W Go Language Specification , wymienia krótki przegląd tagów:
Deklaracja pola może być poprzedzona opcjonalnym znacznikiem string literal, który staje się atrybutem dla wszystkich pól w odpowiednim deklaracja polowa. Znaczniki są widoczne poprzez odbicie interfejs, ale w przeciwnym razie są ignorowane.
// 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" }
To jest bardzo krótkie wyjaśnienie IMO, I zastanawiałem się, czy ktoś mógłby mi podać, jaki byłby pożytek z tych tagów być?
2 answers
Znacznik pola umożliwia dołączenie meta-informacji do pola, które można uzyskać za pomocą odbicia. Zwykle jest on używany do dostarczania informacji o transformacji, jak Pole struct jest zakodowane lub dekodowane z innego formatu (lub przechowywane/pobierane z bazy danych), ale można go użyć do przechowywania dowolnych meta-informacji, które chcesz, albo przeznaczone dla innego pakietu lub do własnego użytku.
Jak wspomniano w dokumentacji reflect.StructTag
, zgodnie z konwencją wartość łańcucha znacznika jest rozdzieloną spacjami listą par key:"value"
, na przykład:
type User struct {
Name string `json:"name" xml:"name"`
}
key
zazwyczaj oznacza pakiet, dla którego przeznaczone jest kolejne "value"
, na przykład json
klucze są przetwarzane/używane przez encoding/json
paczka.
Jeśli w "value"
ma być przekazywana wiele informacji, zwykle określa się je oddzielając przecinkiem (','
), np.
Name string `json:"name,omitempty" xml:"name"`
Zwykle wartość dash ('-'
) dla "value"
oznacza wykluczenie pola z procesu (np. w przypadku json
oznacza nie do marszałka ani nie do rozbrojenia tego pola).
Przykład dostępu do niestandardowych tagów za pomocą refleksji
Możemy użyć odbicia (reflect
pakiet), aby uzyskać dostęp do wartości znaczników pól struct. Zasadniczo musimy nabyć Type
naszej struktury, a następnie możemy odpytywać pola np. za pomocą Type.Field(i int)
lub Type.FieldByName(name string)
. Metody te zwracają wartość StructField
która opisuje / reprezentuje pole struct, a {[20] } jest wartością typu StructTag
które opisuje / reprezentuje wartość znacznika.
Poprzednio mówiliśmy o "konwencji" . Konwencja ta oznacza, że jeśli jej przestrzegasz, możesz użyć StructTag.Get(key string)
metoda, która przetwarza wartość znacznika i zwraca {[7] } z key
, którą podałeś. Metoda jest zaimplementowana / wbudowana w tę metodę Get()
. Jeśli nie zastosujesz się do konwencji, Get()
nie będzie w stanie parsować key:"value"
i znaleźć tego, czego szukasz. To też nie problem, ale wtedy musisz zaimplementować własną logikę parsowania.
Jest też StructTag.Lookup()
(został dodany w Go 1.7), który jest "podobnie jak Get()
, ale odróżnia znacznik nie zawierający podanego klucza od znacznika powiązanego z pustym łańcuchem z podanym kluczem" .
Spójrzmy więc na prosty przykład:
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"))
}
Output (try it on the 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"
[[63]}GopherCon 2015 miał prezentację na temat znaczników struct o nazwie:
The Many Twarze znaczników Struct (slajd) (i wideo )
Oto lista najczęściej używanych kluczy tagów:
-
json
- używane przezencoding/json
pakiet, szczegółowy najson.Marshal()
-
xml
- używane przezencoding/xml
pakiet, szczegółowy naxml.Marshal()
-
bson
- używane przez gobson , wyszczególnione wbson.Marshal()
-
protobuf
- używane przezgithub.com/golang/protobuf/proto
, szczegółowe w opakowaniu doc -
yaml
- używane przezgopkg.in/yaml.v2
pakiet, szczegółowy nayaml.Marshal()
-
db
- używane przezgithub.com/jmoiron/sqlx
Pakiet; używany również przezgithub.com/go-gorp/gorp
pakiet -
orm
- używane przezgithub.com/astaxie/beego/orm
pakiet, szczegółowy na modele-Beego ORM -
gorm
- używane przezgithub.com/jinzhu/gorm
pakiet, przykłady można znaleźć w ich doc: modele -
valid
- używane przezgithub.com/asaskevich/govalidator
pakiet, przykłady można znaleźć na stronie projektu -
datastore
- używane przezappengine/datastore
(Google App Engine platform, Datastore service), wyszczególnione w Properties -
schema
- używane przezgithub.com/gorilla/schema
aby wypełnićstruct
z wartościami formularza HTML, wyszczególnionymi w pakiecie doc -
asn
- używane przezencoding/asn1
pakiet, szczegółowy naasn1.Marshal()
orazasn1.Unmarshal()
-
csv
- używane przezgithub.com/gocarina/gocsv
pakiet
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-31 17:32:15
Oto bardzo prosty przykład tagów używanych z encoding/json
Pakiet kontrolujący interpretację pól podczas kodowania i dekodowania:
Spróbuj na żywo: 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"}
Pakiet json może spojrzeć na Tagi dla pola i dowiedzieć się, jak mapować pole struktury JSON, a także dodatkowe opcje, takie jak czy powinien ignorować puste pola podczas serializacji z powrotem do json.
W zasadzie każdy pakiet może użyć refleksji na pola, aby spojrzeć na wartości znaczników i działać na tych wartościach. Więcej informacji na ich temat znajduje się w pakiecie reflect
http://golang.org/pkg/reflect/#StructTag :
Zgodnie z konwencją, łańcuchy znaczników są konkatenacją opcjonalnie oddzielony spacjami klucz: pary "wartość". Każdy klucz jest niepustym ciągiem znaków składający się ze znaków niekontrolowanych innych niż spacja (U + 0020 " "), quote (U + 0022'"') i colon (U+003A':'). Każda wartość jest cytowana za pomocą U + 0022 znaki "" i Idź ciąg dosłownej składni.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-17 08:21:27