Go中的标签有什么用途?

Go中的标签有什么用途?,go,struct,reflection,tags,Go,Struct,Reflection,Tags,在中,它提到了标签的简要概述: 字段声明后面可以跟一个可选的字符串文字标记, 它将成为对应字段中所有字段的属性 字段声明。通过反射使标记可见 接口,但在其他方面被忽略 // A struct corresponding to the TimeStamp protocol buffer. // The tag strings define the protocol buffer field numbers. struct { microsec uint64 "field 1" serve

在中,它提到了标签的简要概述:

字段声明后面可以跟一个可选的字符串文字标记, 它将成为对应字段中所有字段的属性 字段声明。通过反射使标记可见 接口,但在其他方面被忽略

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

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

下面是一个非常简单的示例,说明了在编码和解码过程中如何使用标记来控制字段的解释:

尝试直播:

主程序包
进口(
“fmt”
“编码/json”
)
类型Person结构{
FirstName字符串`json:“first_name”`
LastName字符串`json:“姓氏”`
MiddleName字符串`json:“中间名称,省略为空”`
}
func main(){
json_字符串:=`
{
“名字”:“约翰”,
“姓氏”:“史密斯”
}`
人员:=新(人员)
Unmarshal([]字节(json_字符串),person)
fmt.Println(人)
新的json,:=json.Marshal(个人)
fmt.Printf(“%s\n”,新的\u json)
}
//*产出*
//&{John Smith}
//{“名字”:“约翰”,“姓氏”:“史密斯”}
json包可以查看字段的标记,并被告知如何映射json struct字段,还可以提供额外的选项,如在序列化回json时是否应忽略空字段

基本上,任何包都可以使用字段上的反射来查看标记值并对这些值进行操作。在reflect软件包中有更多关于它们的信息
:

按照惯例,标记字符串是可选的 空格分隔键:“值”对。每个键都是非空字符串 由除空格(U+0020'')以外的非控制字符组成, 引号(U+0022')和冒号(U+003A':')。每个值都使用 U+0022''字符和Go字符串文字语法


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

如的文档中所述,按照惯例,标记字符串的值是一个以空格分隔的
键:“value”
对列表,例如:

type User struct {
    Name string `json:"name" xml:"name"`
}
type User struct {
    FirstName string `json:"first_name"`
    LastName string `json:"last_name"`
}
通常表示后续的
“值”
所针对的包,例如
json
键由包处理/使用

如果要在
的“值”
中传递多个信息,通常通过用逗号(
,“
)分隔来指定,例如

通常,
“value”
的破折号(
“-”
)表示将字段从流程中排除(例如,在
json
的情况下,表示不封送或取消封送该字段)

使用反射访问自定义标记的示例 我们可以使用反射(包)来访问结构字段的标记值。基本上,我们需要获取结构的名称,然后我们可以查询字段,例如使用
Type.Field(i int)
Type.FieldByName(name string)
。这些方法返回一个值,该值描述/表示结构字段;而
StructField.Tag
是一种类型的值,用于描述/表示标记值

之前我们讨论过“公约”。此约定意味着,如果遵循此约定,则可以使用解析标记值并返回指定的
键的
值的方法。该约定被实现/内置在此
Get()
方法中。如果不遵循约定,
Get()
将无法解析
键:“值”
对并找到您要查找的内容。这也不是问题,但是您需要实现自己的解析逻辑

还有一个(在Go 1.7中添加)是“like
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"))
}
输出(在上尝试):


GopherCon 2015有一个关于结构标签的演示,名为:

(和a)

以下是常用标记键的列表:
  • json
    -由包使用,详细信息见
  • xml
    -由软件包使用,详细信息见
  • bson
    -由使用,详细信息见
  • protobuf
    -由使用,在程序包文档中详细说明
  • yaml
    -由软件包使用,详情见
  • db
    -由软件包使用;也用于包装
  • orm
    -由软件包使用,详情见
  • gorm
    -该软件包使用的示例可在其文档中找到:
  • 有效
    -由软件包使用,示例可在项目页面中找到
  • 数据存储
    -由(谷歌应用程序引擎平台,数据存储服务)使用,详情见
  • schema
    -用于用HTML表单值填充
    struct
    ,详细信息见包文档
  • asn
    -由软件包使用,详细信息见和
  • csv
    -由软件包使用

这是一种规范,用于指定包如何处理标记的字段

例如:

type User struct {
    Name string `json:"name" xml:"name"`
}
type User struct {
    FirstName string `json:"first_name"`
    LastName string `json:"last_name"`
}
json标记通知编组了以下用户输出的
json

u := User{
        FirstName: "some first name",
        LastName:  "some last name",
    }
会是这样的:

{"first_name":"some first name","last_name":"some last name"}
另一个例子是
gorm
package标签声明了数据库迁移必须如何完成:

type User struct {
  gorm.Model
  Name         string
  Age          sql.NullInt64
  Birthday     *time.Time
  Email        string  `gorm:"type:varchar(100);unique_index"`
  Role         string  `gorm:"size:255"` // set field size to 255
  MemberNumber *string `gorm:"unique;not null"` // set member number to unique and not null
  Num          int     `gorm:"AUTO_INCREMENT"` // set num to auto incrementable
  Address      string  `gorm:"index:addr"` // create index with name `addr` for address
  IgnoreMe     int     `gorm:"-"` // ignore this field
}
在这个例子中,对于带有gorm标记的
Email
字段,我们在数据库中为t声明相应的列
type Login struct {
    User     string `form:"user" json:"user" xml:"user"  binding:"required"`
    Password string `form:"password" json:"password" xml:"password" binding:"required"`
}


var json Login
if err := c.ShouldBindJSON(&json); err != nil {
     c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
     return
}