当前位置: 首页 > 面试题库 >

Go中标签的用途是什么?

谢烨烨
2023-03-14
问题内容

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

字段声明后可以跟一个可选的字符串文字标签,该标签成为相应字段声明中所有字段的属性。这些标签通过反射界面可见,但在其他情况下将被忽略。

// 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的简短解释,我想知道是否有人可以为我提供这些标签的用途?


问题答案:

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

如的文档所述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描述/表示一个struct字段;并且StructField.TagStructTag描述/表示标记值的类型值。

以前我们谈论过 “惯例” 。该公约的手段,如果你遵循它,你可以使用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上有一个关于struct标签的演示,名为:

结构标签的许多面孔(幻灯片)
(和视频)

以下是常用标签键的列表:

  • json-由encoding/json包装使用,详细说明json.Marshal()
  • xml-由encoding/xml包装使用,详细说明xml.Marshal()
  • bson-由gobson使用,详细说明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-用于通过HTML表单值github.com/gorilla/schema填充(struct包文档中有详细说明)
  • asn-由encoding/asn1包装使用,详细说明在asn1.Marshal()asn1.Unmarshal()
  • csv-由github.com/gocarina/gocsv包装使用


 类似资料:
  • 在Go语言规范中,提到了对标签的简要概述: 字段声明之后可能会有一个可选的字符串文字标记,该标记将成为相应字段声明中所有字段的属性。标记通过反射界面可见,但在其他情况下被忽略。 这是一个非常简短的解释,我想知道是否有人能给我提供这些标签的用途?

  • 问题内容: 通过与这个有关标签的问题进行类比,我注意到,除了纯注释之外,注释还有多种用途。 例子: go:generate可用于代码生成。 godoc使用函数名称表示应解释的注释 建立约束 还有其他我想念的吗? 那里有确定的清单吗? gocontracts和go- swagger 等一些第三方软件包也可以使用它们。他们如何避免彼此冲突? 问题答案: 如前所述,注释不仅是注释,而且是指令。 撰写本文

  • 问题内容: 当在标记界面中没有什么要实现的东西时,实现它有什么用? 问题答案: 在Java的早期版本中,标记接口是声明有关类的元数据的唯一方法。例如,可序列化标记接口使类的作者可以说他们的类在进行序列化和反序列化时将表现正确。 在现代Java中,标记接口没有位置。它们可以完全由Annotations代替,从而具有非常灵活的元数据功能。如果你具有有关类的信息,并且该信息永不更改,则注释是表示它的非常

  • 问题内容: 我对Bash脚本非常陌生,有人可以向我解释$#和$的情况吗?在以下代码中工作? 问题答案: 在Y分钟内来自Learn Bash :