1)Tag是Struct的一部分


Tag用于标识结构体字段的额外属性,有点类似于注释。标准库reflect包中提供了操作Tag的方法,在介绍方法前,有必要先了解一下结构体的字段是如何表示的。
在reflect包中,使用结构体structField表示结构体的一个字段:
可以看出,Tag也是字段的一个组成部分。Tag 的类型为structTag,实际上它是一个string类型的别名

type StructField struct {
Name string
//字段名
Type Type
//字段类型
Tag StructTag
//Tag
}

2)Tag 约定


Tag 本身是一个字符串,单从语义上讲,任意的字符串都是合法的。但它有一个约定的格式,那就是字符串由key : "value"组成。
key:必须是非空字符串,字符串不能包含控制字符、空格、引号、冒号;

value:以双引号标记的字符串。


注意: key和 value之间使用冒号分隔,冒号前后不能有空格,多个key : "value"之间由空格分开。
 

Kind string 'json:"kind, omitempty" protobuf:"bytes,1, opt, name=kind"`

Kind字段中的Tag包含两个key:"value"对,

分别是json: "kind, omitempty"

protobuf :"bytes,1,opt, name=kind"。
key一般表示用途,比如.json表示用于控制结构体类型与JSON格式数据之间的转换,protobuf表示用于控制序列化和反序列化。value一般表示控制指令,具体控制指令由不同的库指定。


3)Tag的意义


Go语言的反射特性可以动态地给结构体成员赋值,正是因为有Tag,在赋值前可以使用Tag来决定赋值的动作。
比如,官方的encoding/json包可以将一个JSON 数据“Unmarshal”进一个结构体,此过程中就使用了 Tag。该包定义了一些Tag 规则,只要参考该规则设置rag 就可以将不同的JSON数据转换成结构体。