What are the use(s) for tags in Go?
在Go语言规范中,它提到了标签的简要概述:
A field declaration may be followed by an optional string literal tag,
which becomes an attribute for all the fields in the corresponding
field declaration. The tags are made visible through a reflection
interface but are otherwise ignored.
1
2
3
4
5
6
7 // 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的简短说明,我想知道是否有人可以为我提供这些标签的用途?
字段标记允许您将元信息附加到可以使用反射获取的字段上。通常,它用于提供有关如何将结构域编码为另一种格式(或从另一种格式存储(或从数据库中检索))的转换信息,但是您可以使用它存储想要存储的任何元信息,这些元信息既可以用于另一个包装或供您自己使用。
如
1 2 3 | type User struct { Name string `json:"name" xml:"name"` } |
如果要在
1 | Name string `json:"name,omitempty" xml:"name"` |
通常,
使用反射访问自定义标签的示例
我们可以使用反射(
先前我们谈论过"公约"。此约定意味着,如果遵循该约定,则可以使用
还有
因此,让我们看一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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(" Field: User.%s ", fieldName) fmt.Printf("\tWhole tag value : %q ", field.Tag) fmt.Printf("\tValue of 'mytag': %q ", field.Tag.Get("mytag")) } |
输出(在Go Playground上尝试):
1 2 3 4 5 6 7 | 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上有一个关于struct标签的演示,名为:
结构标签的许多面孔(幻灯片)(和视频)
以下是常用标签键的列表:
-
json -由encoding/json 包使用,在json.Marshal() 中有详细说明 -
xml -由encoding/xml 软件包使用,详细信息在xml.Marshal() -
bson -由高布森使用,详细说明在bson.Marshal() -
protobuf -由github.com/golang/protobuf/proto 使用,在软件包doc中有详细说明 -
yaml -由gopkg.in/yaml.v2 包使用,在yaml.Marshal() 中有详细说明 -
db -由github.com/jmoiron/sqlx 软件包使用;也被github.com/go-gorp/gorp 包使用 -
orm -由github.com/astaxie/beego/orm 包使用,在"模型– Beego ORM"中有详细说明 -
gorm -由github.com/jinzhu/gorm 包使用,示例可以在其文档中找到:模型 -
valid -由github.com/asaskevich/govalidator 包使用,示例可以在项目页面中找到 -
datastore -由appengine/datastore (Google App Engine平台,数据存储服务)使用,在"属性"中有详细说明 -
schema -由github.com/gorilla/schema 用于用HTML表单值填充struct ,详细信息在软件包doc中 -
asn -由encoding/asn1 软件包使用,在asn1.Marshal() 和asn1.Unmarshal() 中有详细说明 -
csv -由github.com/gocarina/gocsv 包使用
这是一个非常简单的示例,该标签与
尝试直播:http://play.golang.org/p/BMeR8p1cKf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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 ", new_json) } // *Output* // &{John Smith } // {"first_name":"John","last_name":"Smith"} |
json包可以查看该字段的标签,并被告知如何映射json <=> struct字段,以及其他选项,例如在序列化回json时是否应忽略空字段。
基本上,任何包都可以在字段上使用反射来查看标记值并对其执行操作。在反射包中有一些关于它们的更多信息
http://golang.org/pkg/reflect/#StructTag:
By convention, tag strings are a concatenation of optionally
space-separated key:"value" pairs. Each key is a non-empty string
consisting of non-control characters other than space (U+0020 ' '),
quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted using
U+0022 '"' characters and Go string literal syntax.