In der Go-Sprachspezifikation wird eine kurze Übersicht über Tags erwähnt:
Auf eine Felddeklaration kann ein optionales String-Literal-Tag folgen, das zu einem Attribut für alle Felder in der entsprechenden Felddeklaration wird. Die Tags werden über eine Reflektionsschnittstelle sichtbar gemacht, ansonsten jedoch ignoriert.
// 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" }
Dies ist eine sehr kurze Erklärung, IMO, und ich habe mich gefragt, ob mir jemand mitteilen könnte, welchen Nutzen diese Tags haben würden.
go
reflection
struct
Liamzebedee
quelle
quelle
Antworten:
Mit einem Tag für ein Feld können Sie dem Feld Metainformationen hinzufügen, die mithilfe von Reflektion erfasst werden können. Normalerweise wird es verwendet, um Transformationsinformationen darüber bereitzustellen, wie ein Strukturfeld in ein anderes Format codiert oder aus diesem dekodiert (oder aus einer Datenbank gespeichert / abgerufen) wird. Sie können es jedoch verwenden, um die gewünschten Metainformationen zu speichern, die entweder für ein anderes bestimmt sind Paket oder für den eigenen Gebrauch.
Wie in der Dokumentation von erwähnt
reflect.StructTag
, ist der Wert einer Tag-Zeichenfolge gemäß Konvention eine durch Leerzeichen getrennte Liste vonkey:"value"
Paaren, zum Beispiel:Das
key
bezeichnet normalerweise das Paket,"value"
für das das nachfolgende bestimmt ist, zum Beispiel werdenjson
Schlüssel vomencoding/json
Paket verarbeitet / verwendet .Wenn mehrere Informationen in der übergeben werden sollen
"value"
, wird dies normalerweise durch Trennen durch ein Komma (','
) angegeben, zNormalerweise bedeutet ein Strichwert (
'-'
) für das"value"
Mittel, um das Feld vom Prozess auszuschließen (z. B. wennjson
dies bedeutet, dass dieses Feld nicht gemarshallt oder unmarshallt wird).Beispiel für den Zugriff auf Ihre benutzerdefinierten Tags mithilfe von Reflection
Wir können Reflection (
reflect
Paket) verwenden, um auf die Tag-Werte von Strukturfeldern zuzugreifen. Grundsätzlich müssen wir dieType
unserer Struktur erwerben , und dann können wir Felder abfragen, z . B. mitType.Field(i int)
oderType.FieldByName(name string)
. Diese Methoden geben einen Wert zurück, derStructField
ein Strukturfeld beschreibt / darstellt. undStructField.Tag
ist ein Wert vom Typ,StructTag
der einen Tag-Wert beschreibt / darstellt.Zuvor haben wir über "Konvention" gesprochen . Diese Konvention bedeutet, dass Sie, wenn Sie sie befolgen, die
StructTag.Get(key string)
Methode verwenden können, die den Wert eines Tags analysiert und Ihnen den"value"
vonkey
Ihnen angegebenen Wert zurückgibt . Die Konvention ist in dieseGet()
Methode implementiert / eingebaut . Wenn Sie die Konvention nicht befolgen,Get()
können Sie keinekey:"value"
Paare analysieren und finden, wonach Sie suchen. Das ist auch kein Problem, aber dann müssen Sie Ihre eigene Parsing-Logik implementieren.Es gibt auch
StructTag.Lookup()
(wurde in Go 1.7 hinzugefügt), das "ähnlich ist,Get()
aber das Tag, das den angegebenen Schlüssel nicht enthält, von dem Tag unterscheidet, das dem angegebenen Schlüssel eine leere Zeichenfolge zuordnet" .Schauen wir uns also ein einfaches Beispiel an:
Ausgabe (versuchen Sie es auf dem Go-Spielplatz ):
GopherCon 2015 hatte eine Präsentation über Struktur-Tags mit dem Namen:
Die vielen Gesichter von Struktur-Tags (Folie) (und ein Video )
Hier ist eine Liste häufig verwendeter Tag-Schlüssel:
json
- vomencoding/json
Paket verwendet, detailliert unterjson.Marshal()
xml
- vomencoding/xml
Paket verwendet, detailliert unterxml.Marshal()
bson
- von gobson verwendet , detailliert unterbson.Marshal()
protobuf
- verwendet vongithub.com/golang/protobuf/proto
, detailliert im Paketdokumentyaml
- vomgopkg.in/yaml.v2
Paket verwendet, detailliert unteryaml.Marshal()
db
- vomgithub.com/jmoiron/sqlx
Paket verwendet; wird auch vomgithub.com/go-gorp/gorp
Paket verwendetorm
- Wird vomgithub.com/astaxie/beego/orm
Paket verwendet und ist bei Models - Beego ORM aufgeführtgorm
- Beispiele, die vomgithub.com/jinzhu/gorm
Paket verwendet werden, finden Sie in ihrem Dokument: Modellevalid
- Beispiele, die vomgithub.com/asaskevich/govalidator
Paket verwendet werden, finden Sie auf der Projektseitedatastore
- verwendet vonappengine/datastore
(Google App Engine-Plattform, Datenspeicherdienst), detailliert unter Eigenschaftenschema
- wird verwendetgithub.com/gorilla/schema
, um astruct
mit HTML-Formularwerten zu füllen , die im Paketdokument aufgeführt sindasn
- vomencoding/asn1
Paket verwendet, detailliert unterasn1.Marshal()
undasn1.Unmarshal()
csv
- vomgithub.com/gocarina/gocsv
Paket verwendetquelle
Hier ist ein wirklich einfaches Beispiel für Tags, die mit dem
encoding/json
Paket verwendet werden, um zu steuern, wie Felder während des Codierens und Decodierens interpretiert werden:Versuchen Sie es live: http://play.golang.org/p/BMeR8p1cKf
Das json-Paket kann sich die Tags für das Feld ansehen und erfahren, wie das json <=> -Strukturfeld zugeordnet wird, sowie zusätzliche Optionen, z. B. ob leere Felder bei der Serialisierung zurück zu json ignoriert werden sollen.
Grundsätzlich kann jedes Paket die Felder reflektieren, um Tag-Werte anzuzeigen und auf diese Werte zu reagieren. Weitere Informationen dazu finden Sie im Reflect-Paket
http://golang.org/pkg/reflect/#StructTag :
quelle
Es handelt sich um eine Art von Spezifikation, die angibt, wie Pakete mit einem mit Tags versehenen Feld behandelt werden.
zum Beispiel:
Das json-Tag informiert das
json
Paket darüber, dass die Ausgabe des folgenden Benutzers gemarshallt wurdewäre so:
Ein anderes Beispiel ist, dass
gorm
Paket-Tags deklarieren, wie Datenbankmigrationen durchgeführt werden müssen:In diesem Beispiel für das Feld
Email
mit dem Gorm-Tag deklarieren wir, dass die entsprechende Spalte in der Datenbank für die Feld-E-Mail vom Typ varchar und maximal 100 sein muss und außerdem einen eindeutigen Index haben muss.Ein anderes Beispiel sind
binding
Tags, die meistens imgin
Paket verwendet werden.Das Bindungs-Tag in diesem Beispiel gibt dem Gin-Paket einen Hinweis darauf, dass die an die API gesendeten Daten Benutzer- und Kennwortfelder enthalten müssen, da diese Felder nach Bedarf markiert werden.
Generell sind Tags Daten, die Pakete benötigen, um zu wissen, wie sie mit Daten unterschiedlicher Strukturen umgehen sollen. Der beste Weg, sich mit den Tags vertraut zu machen, die ein Paket benötigt, ist das vollständige Lesen einer Paketdokumentation.
quelle