问题描述
字段的标签允许您将元信息附加到可以使用反射获取的字段。通常它用于提供有关如何将结构字段编码为另一种格式或从另一种格式解码(或从数据库中存储/检索)的转换信息,但您可以使用它来存储您想要的任何元信息,或者用于另一个打包或供您自己使用。
正如在 的文档中提到的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)
它解析变量的值,并返回该方法"value"
的key
指定。该约定已实现/内置到此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 有一个关于结构标签的演示,称为:
(和视频)
以下是常用标签键的列表:
-
json
- 由encoding/json
包使用,详情见json.Marshal()
-
xml
- 由encoding/xml
包使用,详情见xml.Marshal()
-
bson
- 由gobson 使用,详情见bson.Marshal()
; 也由mongo-go驱动程序提供,在bson package doc 中有详细说明 -
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
包使用,详细见模型 – Beego ORM -
gorm
- 使用gorm.io/gorm
,示例可以在他们的文档中找到 -
valid
- 由github.com/asaskevich/govalidator
包使用,示例可以在项目页面中找到 -
datastore
- 由appengine/datastore
(Google App Engine 平台、Datastore 服务)使用,详情见属性 -
schema
- 用于github.com/gorilla/schema
填充struct
HTML 表单值,在包文档中有详细说明 -
asn
- 由encoding/asn1
包使用,详情见asn1.Marshal()
和asn1.Unmarshal()
-
csv
- 由github.com/gocarina/gocsv
包使用 -
env
- 由github.com/caarlos0/env
包使用
解决方法
在Go Language Specification 中,它提到了标签的简要概述:
字段声明后可以跟一个可选的字符串文字标记,它成为相应字段声明中所有字段的属性。标签通过反射界面可见,但会被忽略。
golang // 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 的一个非常简短的解释,我想知道是否有人可以向我提供这些标签的用途?