Go 中标签的用途是什么? [英] What are the use(s) for tags in Go?

查看:29
本文介绍了Go 中标签的用途是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Go语言规范中,它提到了标签的简要概述:

In the Go Language Specification, it mentions a brief overview of tags:

一个字段声明可以跟一个可选的字符串文字标签,它成为相应字段中所有字段的属性字段声明.标签通过反射可见接口,否则会被忽略.

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"
}

这是 IMO 的一个非常简短的解释,我想知道是否有人可以向我提供这些标签的用途?

This is a very short explanation IMO, and I was wondering if anyone could provide me with what use these tags would be?

推荐答案

字段的标签允许您将元信息附加到可以使用反射获取的字段.通常它用于提供有关结构字段如何编码为另一种格式或从另一种格式解码(或从数据库中存储/检索)的转换信息,但您可以使用它来存储您想要的任何元信息,或者用于另一个打包或供您自己使用.

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.

reflect.StructTag的文档中所述,按照惯例,标签字符串的值是以空格分隔的 key:value" 对列表,例如:

type User struct {
    Name string `json:"name" xml:"name"`
}

key 通常表示后续value" 所针对的包,例如json 键被处理/使用encoding/json 包.

The key usually denotes the package that the subsequent "value" is for, for example json keys are processed/used by the encoding/json package.

如果要在value"中传递多个信息,通常用逗号分隔(',')来指定,例如

If multiple information is to be passed in the "value", usually it is specified by separating it with a comma (','), e.g.

Name string `json:"name,omitempty" xml:"name"`

通常,值" 的破折号值 ('-') 意味着从进程中排除该字段(例如在 json 表示不编组或解组该字段).

Usually a dash value ('-') for the "value" means to exclude the field from the process (e.g. in case of json it means not to marshal or unmarshal that field).

我们可以使用反射(reflect 包)来访问标签结构字段的值.基本上我们需要获取结构的Type,然后我们可以查询字段,例如使用 Type.Field(i int)Type.FieldByName(name string).这些方法返回一个 StructField 的值,它描述/代表一个结构场地;并且 StructField.Tag 是 [StructTag] 6 描述/代表一个标签值.

We can use reflection (reflect package) to access the tag values of struct fields. Basically we need to acquire the Type of our struct, and then we can query fields e.g. with Type.Field(i int) or Type.FieldByName(name string). These methods return a value of StructField which describes / represents a struct field; and StructField.Tag is a value of type [StructTag] 6 which describes / represents a tag value.

之前我们谈到了约定".这个约定意味着如果你遵循它,你可以使用 StructTag.Get(key string) 方法解析标签的值并返回您指定的value".约定已实现/内置到此 Get() 方法中.如果您不遵守约定,Get() 将无法解析 key:"value" 对并找到您要查找的内容.这也不是问题,但是你需要实现自己的解析逻辑.

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. The convention is implemented / built into this Get() method. If you don't follow the convention, Get() will not be able to parse key:"value" pairs and find what you're looking for. That's also not a problem, but then you need to implement your own parsing logic.

还有 StructTag.Lookup()(在 Go 1.7 中添加)它类似于 Get(),但将不包含给定键的标签与将空字符串与给定键相关联的标签区分开来".

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".

让我们看一个简单的例子:

So let's see a simple example:

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("
Field: User.%s
", fieldName)
    fmt.Printf("	Whole tag value : %q
", field.Tag)
    fmt.Printf("	Value of 'mytag': %q
", field.Tag.Get("mytag"))
}

输出(在 Go Playground 上试试):

Output (try it on the 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 有一个关于结构标签的演示,称为:


GopherCon 2015 had a presentation about struct tags called:

结构标签的多面性(幻灯片)(以及 视频)

  • json      - used by the encoding/json package, detailed at json.Marshal()
  • xml       - used by the encoding/xml package, detailed at xml.Marshal()
  • bson      - used by gobson, detailed at bson.Marshal(); also by the mongo-go driver, detailed at bson package doc
  • protobuf  - used by github.com/golang/protobuf/proto, detailed in the package doc
  • yaml      - used by the gopkg.in/yaml.v2 package, detailed at yaml.Marshal()
  • db        - used by the github.com/jmoiron/sqlx package; also used by github.com/go-gorp/gorp package
  • orm       - used by the github.com/astaxie/beego/orm package, detailed at Models – Beego ORM
  • gorm      - used by gorm.io/gorm, examples can be found in their docs
  • valid     - used by the github.com/asaskevich/govalidator package, examples can be found in the project page
  • datastore - used by appengine/datastore (Google App Engine platform, Datastore service), detailed at Properties
  • schema    - used by github.com/gorilla/schema to fill a struct with HTML form values, detailed in the package doc
  • asn       - used by the encoding/asn1 package, detailed at asn1.Marshal() and asn1.Unmarshal()
  • csv       - used by the github.com/gocarina/gocsv package
  • env - used by the github.com/caarlos0/env package

这篇关于Go 中标签的用途是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆