Go 的结构体标签
发布日期:2022-02-01 16:54:09 浏览次数:39 分类:技术文章

本文共 2805 字,大约阅读时间需要 9 分钟。

掌握了Go语言的朋友们应该都知道,在Go的结构体类型声明里面,字段声明后可以跟一个可选的字符串标签。

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

上面是一个标准的例子,Name字段声明中指定了标签json:"name" xml:"name" ,这个标签值看着有点类似Java程序里给类属性加的注解。

那么这些结构体标签有什么用途呢,我们随便写管用吗?我们平时工作中常用的结构体标签有哪些呢?我们能不能自己定义结构体标签?今天就带大家掰扯清楚这些问题!

结构体标签

Go语言允许我们通过结构体字段标签给一个字段附加可以被反射获取的”元信息“,正好我们上篇文章中讲了Go语言反射使用方法相关的内容,对反射不清楚的可以先去再复习一下。

通常情况下,结构体标签被用于提供结构体字段如何被编码为或者解码自另外一种格式的转换信息(或者是以何种形式被保存至/获取自数据库)。不过,你也可以用它存储任何你想要设置的”元信息“,供其他包或者自己使用。

使用规范

结构体标签在使用上通常是遵守下面三个规范。

结构体标签字符串的值是一个由空格分隔的 key:"value" 对列表,例如:

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

键,通常表示后面跟的“值”是被哪个包使用的,例如json这个键会被encoding/json包处理使用。如果要在“键”对应的“值”中传递多个信息,通常通过用逗号(',')分隔来指定,例如

Name string `json:"name,omitempty"`

按照惯例,如果一个字段的结构体标签里某个键的“值”被设置成了的破折号 ('-'),那么就意味着告诉处理该结构体标签键值的进程排除该字段。例如,把一个字段的标签设置成下面这样

Name string `json:"-"`

就以为进行JSON编码/解码时忽略Name这个字段。

怎么获取到结构体标签

从一开始我们就说结构体标签是给反射准备的,那么怎么在Go程序里用反射获得到字段的结构体标签呢?看了我们上一篇文章的同学,应该会知道,结构体字段类型相关的信息,在反射的世界里使用reflect.StructFiled这个类型表示的。

type StructField struct { Name string Type      Type      // field type Tag       StructTag // field tag string  ......}

如上所示,其中包含的Tag字段即代表了字段声明中的结构体标签信息。让我们通过自定义结构体标签的例子来演示一下怎么使用它在反射里读取到标签里的信息。

用反射获取到自定义的结构体标签

使用反射reflect包访问结构体字段的标签值,我们需要先获取到结构体的类型信息Type,然后使用Type.Field(i int)Type.FieldByName(name string),方法查询字段信息,这两个方法都会返回一个StructField类型的值,上面我们也说了它在反射的世界里用于描述一个结构体字段;而StructField.Tag 是一个StructTag 类型的值,它描述了字段的标签。

上面我们谈到了结构体标签的使用规范,如果遵循规范给字段设置了标签后,就可以使用StructTagGet方法解析标签的值并返回你指定的键的“值”。

func (tag StructTag) Get(key string) string

为了方便判断一个给定的key是否存在与标签中,StructTag还提供了一个Lookup方法

func (tag StructTag) Lookup(key string) (value string, ok bool)

Get方法不同的是,Lookup会通过返回的ok值告知给定key是否存在与标签中。

下面通过一个例子,演示下获取我们自定义标签的过程。

package mainimport ( "fmt" "reflect")type User struct { Name  string `mytag:"MyName"` Email string `mytag:"MyEmail"`}func main() { u := User{"Bob", "bob@mycompany.com"} t := reflect.TypeOf(u) for i := 0; i < t.NumField(); i++ {  field := t.Field(i)  fmt.Printf("Field: User.%s\n", field.Name)  fmt.Printf("\tWhole tag value : %s\n", field.Tag)  fmt.Printf("\tValue of 'mytag': %s\n", field.Tag.Get("mytag")) }}

上面的程序会输出

Field: User.Name        Whole tag value : mytag:"MyName"        Value of 'mytag': MyNameField: User.Email        Whole tag value : mytag:"MyEmail"        Value of 'mytag': MyEmail

常用的结构体标签键

常用的结构体标签Key,指的是那些被一些常用的开源包声明使用的结构体标签键。在这里总结了一些,都是一些我们平时会用到的包,它们是:

  • json:  由encoding/json 包使用,详见json.Marshal()的使用方法和实现逻辑。

  • xml :  由encoding/xml包使用,详见xml.Marshal()

  • bson:  由gobson包,和mongo-go包使用。

  • protobuf:  由github.com/golang/protobuf/proto 使用,在包文档中有详细说明。

  • yaml:  由gopkg.in/yaml.v2 包使用,详见yaml.Marshal()

  • gorm:  由gorm.io/gorm包使用,示例可以在GORM的文档中找到。

当然这里列的就是最常用的几个库他们提供给我们使用的结构体标签,欢迎大伙踊跃留言,补充一些自己平时用过的库提供给开发者使用的结构体标签

总结

这篇文章算是我们上一篇讲Go反射的一个实践方向的延伸介绍,如果你也想在自己的包里提供一些结构体标签键,让自己的包更易用些,除了看咱们这篇文章外,还可以去看看上面咱们介绍的几个类库,看它们的源码里是怎么应用的,现学现用!

转载地址:https://blog.csdn.net/slphahaha/article/details/122098571 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:诱发 Goroutine 挂起的众多原因
下一篇:推荐几个干货公众号

发表评论

最新留言

不错!
[***.144.177.141]2024年03月26日 20时45分56秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

python类属性初始化_Python类定义、属性、初始化和析构 2019-04-21
mysql构建url给scrapy_Python Scrapy从mysq填充起始url 2019-04-21
owdcloud mysql_MySQL在Ubuntu远程配置 2019-04-21
python基础装饰器_Python基础 装饰器及练习 2019-04-21
python导出csv不带引号的句子_不带双引号写入CSV文件 2019-04-21
python爬虫代码模板_Python:学习Python爬虫的第一天 2019-04-21
springboot获取原生js请求_springboot跳转原生html 2019-04-21
java buffer nio_Java NIO之Buffer(缓冲区)入门 2019-04-21
android java加密_android 和java平台通用的AES加密解密 2019-04-21
java导出类_java导出excel工具类 2019-04-21
java学习手册下载_Java学习手册 2019-04-21
axios delete有请求体吗_关于axios请求——delete方法 2019-04-21
java 自助更改密码 api_搭建ldap自助修改密码系统--Self Service Password 2019-04-21
php继承exten,stylus中文文档 » 继承(@extend) » 张鑫旭-鑫空间-鑫生活 2019-04-21
mysql函数大全 pdf,MySQL函数大全 2019-04-21
php 常用文件系统函数,php 文件系统函数整理介绍 2019-04-21
android pm.java,java – AM / PM的Android DateFormat因设备而异 2019-04-21
oracle存储过程调用sql文件,oracle - 在SQL Developer中运行存储过程? 2019-04-21
oracle同时报604和12507,V$SES_OPTIMIZER_ENV 查不到刚修改的隐含参数, 2019-04-21
zblog的php更换域名,zblogphp更换域名后,原zblog里使用了固定域名,登录不进去怎么办... 2019-04-21