字段的标签允许您将元信息附加到可以使用反射获取的字段。通常它用于提供有关如何将结构字段编码为另一种格式或从另一种格式解码(或从数据库中存储/检索)的转换信息,但您可以使用它来存储您想要的任何元信息,或者用于另一个打包或自用。
正如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 包)来访问结构字段的标记值。基本上我们需要获取结构体的Type,然后我们可以查询字段,例如与Type.Field(i int) 或Type.FieldByName(name string)。这些方法返回一个值StructField,它描述/表示一个结构字段; StructField.Tag 是 [StructTag] 6 类型的值,它描述/表示标签值。
之前我们谈到了“约定”。这个约定意味着如果你遵循它,你可以使用 StructTag.Get(key string) 方法来解析标签的值并返回你指定的 key 中的 "value"。 约定已实现/内置到此Get() 方法中。如果您不遵守约定,Get() 将无法解析 key:"value" 对并找到您要查找的内容。这也不是问题,但是你需要实现自己的解析逻辑。
还有StructTag.Lookup()(在 Go 1.7 中添加)“类似于 Get(),但将不包含给定键的标签与将空字符串与给定键相关联的标签区分开来”.
让我们看一个简单的例子:
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"))
}
输出(在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 有一个关于结构标签的演讲,名为:
The Many Faces of Struct Tags (slide)(和一个video)
这里是常用的标签键列表: