Go Language Specification では、タグの概要を説明しています。
フィールド宣言の後には、オプションの文字列リテラルタグを続けることができます。これは、対応するフィールド宣言内のすべてのフィールドの属性になります。タグはリフレクションインタフェースを通して表示されますが、それ以外は無視されます。
// 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" }
これはIMOの非常に短い説明です、そして、誰かがこれらのタグの用途が何かを私に提供することができるかどうか疑問に思いましたか?
フィールドのタグを使用すると、リフレクションを使用して取得できるフィールドにメタ情報を添付することができます。通常、structフィールドが他のフォーマットにエンコードされたりデコードされたりする方法(またはデータベースに格納/取得される方法)に関する変換情報を提供するために使用されますが、目的のメタ情報を格納するために使用できます。パッケージまたはあなた自身の使用のために。
reflect.StructTag
のドキュメントで述べたように、慣例により、タグ文字列の値はkey:"value"
ペアのスペース区切りのリストです。次に例を示します。
type User struct {
Name string `json:"name" xml:"name"`
}
key
は通常、後続の"value"
が対象とするパッケージを表します。たとえば、json
キーは encoding/json
パッケージによって処理または使用されます。
複数の情報を"value"
に渡す場合は、通常、カンマ(','
)で区切って指定します。
Name string `json:"name,omitempty" xml:"name"`
通常、'-'
のダッシュ値("value"
)はプロセスからフィールドを除外することを意味します(例えばjson
の場合、それはそのフィールドを整列化または非整列化しないことを意味します)。
リフレクション( reflect
package)を使って構造体フィールドのタグ値にアクセスすることができます。基本的には、構造体の Type
を取得する必要があります。それからフィールドを問い合わせることができますType.Field(i int)
またはType.FieldByName(name string)
と一緒に。これらのメソッドは StructField
という値を返します。 StructField.Tag
は StructTag
というタイプの値で、タグ値を記述したり表します。
以前は「規約」について説明しました。この規則は、それに従えば、タグの値を解析して指定したkey
の"value"
を返す StructTag.Get(key string)
メソッドを使用できることを意味します。 の規則はこのGet()
メソッドに実装されています。規約に従わないと、Get()
はkey:"value"
ペアを解析して探しているものを見つけることができなくなります。これも問題ではありませんが、それからあなたはあなた自身の解析ロジックを実装する必要があります。
StructTag.Lookup()
のように "である Get()
(Go 1.7で追加された)もありますが、与えられたキーを含まないタグと空の文字列を関連付けるタグを区別します"。
簡単な例を見てみましょう。
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"))
}
出力( 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では、次の構造体タグについての発表がありました。
構造タグのさまざまな面(スライド)(および ビデオ )
json
- encoding/json
パッケージで使用。詳細は json.Marshal()
xml
- encoding/xml
パッケージで使用。詳細は xml.Marshal()
bson
- gobson で使用。詳細は bson.Marshal()
protobuf
- github.com/golang/protobuf/proto
によって使用される、パッケージのドキュメントに詳述されているyaml
- gopkg.in/yaml.v2
パッケージで使用。詳細は yaml.Marshal()
db
- github.com/jmoiron/sqlx
パッケージで使われます。 github.com/go-gorp/gorp
パッケージでも使われていますorm
- github.com/astaxie/beego/orm
パッケージで使用。詳細は Models - Beego ORMgorm
- github.com/jinzhu/gorm
パッケージで使用されます、例は彼らのドキュメントにあります: Modelsvalid
- github.com/asaskevich/govalidator
パッケージで使用されます。例はプロジェクトページにあります。datastore
- appengine/datastore
(Google App Engineプラットフォーム、データストアサービス)で使用。詳細は プロパティschema
- github.com/gorilla/schema
によって使用され、struct
をHTMLフォーム値で埋めるために使用されます。パッケージdocで詳しく説明されていますasn
- encoding/asn1
パッケージで使用。詳細は asn1.Marshal()
および asn1.Unmarshal()
csv
- github.com/gocarina/gocsv
パッケージで使われるこれは encoding/json
パッケージで使われているタグの本当に簡単な例です。
ライブで試す: 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"}
Jsonパッケージはフィールドのタグを調べて、json <=> structフィールドをマップする方法、およびjsonにシリアライズするときに空のフィールドを無視するかどうかなどの追加オプションを指示することができます。
基本的に、どのパッケージでもフィールドのリフレクションを使用してタグ値を調べ、それらの値に基づいて動作できます。リフレクトパッケージにはもう少し詳しい情報があります
http://golang.org/pkg/reflect/#StructTag :
慣例により、タグ文字列は、オプションでスペースで区切られたkey: "value"のペアの連結です。各キーは、スペース(U + 0020 '')、引用符(U + 0022 '"')、およびコロン(U + 003A ':')以外の非制御文字で構成される、空ではない文字列です。 U + 0022 '"'文字とGo文字列リテラル構文を使用する。