注册 登录

清河洛

Go中的结构体标签

qingheluo2024-07-19清河洛147
在Go中,结构体被用来将多个信息聚合在一个单元中,这些信息集合被用来描述更高层次的概念在定义字段时除了字段名和类型外,还可以有一个可选的使用反引号字面量定义的字符串,称之为结构体标签(tag)或结构体字段标签(tag)结构体标签仅仅是作为一个结构体的字段信息描述,或者说是一个字段的注释信息,在程序运行时不会产生任何作用和功能 type User struct { Name string `any str` Password string `any str` Age int `any str` } 标签的内容和格式可以随意编写 ...

在Go中,结构体被用来将多个信息聚合在一个单元中,这些信息集合被用来描述更高层次的概念

在定义字段时除了字段名和类型外,还可以有一个可选的使用反引号字面量定义的字符串,称之为结构体标签(tag)结构体字段标签(tag)

结构体标签仅仅是作为一个结构体的字段信息描述,或者说是一个字段的注释信息,在程序运行时不会产生任何作用和功能

type User struct {
    Name     string   `any str`
    Password string   `any str`
    Age      int      `any str`
}

标签的内容和格式可以随意编写

在实际使用中,可能涉及到结构体数据的序列化或其他转化,比如json转换,ORM数据库操作等,由于Go规定只有首字母大写的变量或字段才是外部可访问的,所以当我们需要使用首字母非大写的格式时就无法实现

如我们需要转化后的json中key为"name"

为了满足常用的序列化需求,在Go的官方reflect包中定义了一种结构体标签的写法规范,用于解析符合该规范的结构体标签

由一个或多个键值对组成,多个键值对之间使用一个空格分割

其中键指定转化类型,值为使用该类型转化时该字段的转化规则

每个键与值使用冒号分隔,且冒号两侧不能有空格

每个值必须使用双引号包含,每个键不能使用任何单引号或双引号

然后使用reflect包中的TypeOf.FieldByName(Field).Get(key)就可以获得对应的值

type User struct {
    Name     string   `json:"any_str"`
    Password string   `any str`
    Age      int      `any str`
}

userInfo     := reflect.TypeOf(user)
nameField, _ := userInfo.FieldByName("Name")
nameTag      := field.Tag.Get("json")   // any_str

很多涉及到结构体字段名称转化或信息补充的包都是基于这个包实现的

常见的如用于json转化的encoding/json包,通过结构体标签设定了结构体在转换为json时使用的字段名、值类型以及当值为空值时是否转换等一系列规则

还有用于ORM操作数据库的gorm.io/gorm包,通过结构体标签设定数据库名、数据类型、主键、自增、唯一、表注释等等几十种规则

还有xml解析(encoding/xml)、from表单(Gin)、ini配置解析(go-ini)等等

我们还可以基于reflect包的这个实现来编写自定义的包并对结构体进行自定义规则的控制

由于实现是基于reflect包这个包级别的而非语言级别的,所以容错能力很差,即使编写不符合规定,编译和运行时都不会提示任何错误



网址导航