Go中的标签有什么用?
本文翻译自:What are the use(s) for tags in Go?
In the Go Language Specification , it mentions a brief overview of tags: 在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. 标签通过反射界面可见,但否则将被忽略。
// 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" }
This is a very short explanation IMO, and I was wondering if anyone could provide me with what use these tags would be? 这是一个非常简短的解释IMO,我想知道是否有人可以提供我这些标签的用途?
#1楼
参考:https://stackoom.com/question/jYrj/Go中的标签有什么用
#2楼
Here is a really simple example of tags being used with the encoding/json
package to control how fields are interpreted during encoding and decoding: 以下是与encoding/json
包一起使用的标签的一个非常简单的示例,用于控制在编码和解码期间如何解释字段:
Try live: http://play.golang.org/p/BMeR8p1cKf 试试直播: 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"}
The json package can look at the tags for the field and be told how to map json <=> struct field, and also extra options like whether it should ignore empty fields when serializing back to json. json包可以查看字段的标记,并告诉如何映射json <=> struct字段,还有额外的选项,例如它是否应该在序列化回json时忽略空字段。
Basically, any package can use reflection on the fields to look at tag values and act on those values. 基本上,任何包都可以使用字段上的反射来查看标记值并对这些值进行操作。 There is a little more info about them in the reflect package 在反射包中有关于它们的更多信息
http://golang.org/pkg/reflect/#StructTag : 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. 每个键都是一个非空字符串,由空格(U + 0020''),引号(U + 0022'“')和冒号(U + 003A':')以外的非控制字符组成。每个值都被引用使用U + 0022'“'字符和Go字符串文字语法。
#3楼
A tag for a field allows you to attach meta-information to the field which can be acquired using reflection. 字段的标记允许您将元信息附加到可以使用反射获取的字段。 Usually it is used to provide transformation info on how a struct field is encoded to or decoded from another format (or stored/retrieved from a database), but you can use it to store whatever meta-info you want to, either intended for another package or for your own use. 通常它用于提供关于如何将结构字段编码到另一种格式或从另一种格式解码(或从数据库存储/检索)的转换信息,但是您可以使用它来存储您想要的任何元信息,或者用于另一个包装或供您自己使用。
As mentioned in the documentation of reflect.StructTag
, by convention the value of a tag string is a space-separated list of key:"value"
pairs, for example: 正如reflect.StructTag
文档中所提到的,按照惯例,标记字符串的值是以空格分隔的key:"value"
列表key:"value"
对,例如:
type User struct {
Name string `json:"name" xml:"name"`
}
The key
usually denotes the package that the subsequent "value"
is for, for example json
keys are processed/used by the encoding/json
package. key
通常表示后续"value"
用于的包,例如json
**由encoding/json
包处理/使用。
If multiple information is to be passed in the "value"
, usually it is specified by separating it with a comma ( ','
), eg 如果要在"value"
传递多个信息,通常通过用逗号( ','
)分隔来指定,例如,
Name string `json:"name,omitempty" xml:"name"`
Usually a dash value ( '-'
) for the "value"
means to exclude the field from the process (eg in case of json
it means not to marshal or unmarshal that field). 通常, "value"
的破折号值( '-'
)表示从过程中排除该字段(例如,在json
情况下,它意味着不对该字段进行编组或解组)。
Example of accessing your custom tags using reflection 使用反射访问自定义标记的示例
We can use reflection ( reflect
package) to access the tag values of struct fields. 我们可以使用反射( reflect
包)来访问struct字段的标记值。 Basically we need to acquire the Type
of our struct, and then we can query fields eg with Type.Field(i int)
or Type.FieldByName(name string)
. 基本上我们需要获取结构的Type
,然后我们可以查询字段,例如使用Type.Field(i int)
或Type.FieldByName(name string)
。 These methods return a value of StructField
which describes / represents a struct field; 这些方法返回StructField
的值,该值描述/表示struct字段; and StructField.Tag
is a value of type StructTag
which describes / represents a tag value. 和StructField.Tag
是类型的值StructTag
其描述/表示标记值。
Previously we talked about "convention" . 以前我们谈过“会议” 。 This convention means that if you follow it, you may use the StructTag.Get(key string)
method which parses the value of a tag and returns you the "value"
of the key
you specify. 此约定意味着如果您遵循它,您可以使用StructTag.Get(key string)
方法来解析标记的值并返回您指定的key
的"value"
。 The convention is implemented / built into this Get()
method. 该约定在此Get()
方法中实现/内置。 If you don't follow the convention, Get()
will not be able to parse key:"value"
pairs and find what you're looking for. 如果你不遵循惯例, Get()
将无法解析key:"value"
对并找到你要找的东西。 That's also not a problem, but then you need to implement your own parsing logic. 这也不是问题,但是你需要实现自己的解析逻辑。
Also there is StructTag.Lookup()
(was added in Go 1.7) which is "like Get()
but distinguishes the tag not containing the given key from the tag associating an empty string with the given key" . 还有StructTag.Lookup()
(在Go 1.7中添加),它“像Get()
但是将不包含给定键的标记与将空字符串与给定键关联的标记区分开来 。
So let's see a simple example: 让我们看一个简单的例子:
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"))
}
Output (try it on the Go Playground ): 输出(在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 had a presentation about struct tags called: GopherCon 2015有一个关于struct标签的演示文稿:
The Many Faces of Struct Tags (slide) (and a video ) 结构标签的多面(幻灯片) (和视频 )
Here is a list of commonly used tag keys: 以下是常用标记键的列表:
-
json
- used by theencoding/json
package, detailed atjson.Marshal()
json
- 由encoding/json
包使用,详见json.Marshal()
-
xml
- used by theencoding/xml
package, detailed atxml.Marshal()
xml
- 由encoding/xml
包使用,详细信息在xml.Marshal()
-
bson
- used by gobson , detailed atbson.Marshal()
bson
- 由gobson使用 ,详见bson.Marshal()
-
protobuf
- used bygithub.com/golang/protobuf/proto
, detailed in the package docprotobuf
- 由github.com/golang/protobuf/proto
,详见包doc -
yaml
- used by thegopkg.in/yaml.v2
package, detailed atyaml.Marshal()
yaml
- 由gopkg.in/yaml.v2
包使用,详细信息在yaml.Marshal()
-
db
- used by thegithub.com/jmoiron/sqlx
package;db
- 由github.com/jmoiron/sqlx
包使用; also used bygithub.com/go-gorp/gorp
package 也被github.com/go-gorp/gorp
包使用 -
orm
- used by thegithub.com/astaxie/beego/orm
package, detailed at Models – Beego ORMorm
- 由github.com/astaxie/beego/orm
包使用,详见Models - Beego ORM -
gorm
- used by thegithub.com/jinzhu/gorm
package, examples can be found in their doc: Modelsgorm
- 由github.com/jinzhu/gorm
包使用,示例可以在他们的doc: Models中找到 -
valid
- used by thegithub.com/asaskevich/govalidator
package, examples can be found in the project pagevalid
- 由github.com/asaskevich/govalidator
包使用,示例可以在项目页面中找到 -
datastore
- used byappengine/datastore
(Google App Engine platform, Datastore service), detailed at Propertiesdatastore
- 由appengine/datastore
(Google App Engine平台,数据存储区服务)使用,详见属性 -
schema
- used bygithub.com/gorilla/schema
to fill astruct
with HTML form values, detailed in the package docschema
- 由github.com/gorilla/schema
用于填充包含HTML表单值的struct
,详见包doc -
asn
- used by theencoding/asn1
package, detailed atasn1.Marshal()
andasn1.Unmarshal()
asn
- 由encoding/asn1
包使用,详细信息在asn1.Marshal()
和asn1.Unmarshal()
-
csv
- used by thegithub.com/gocarina/gocsv
packagecsv
- 由github.com/gocarina/gocsv
包使用
上一篇: 最爱老婆吵架最令人生畏