脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - 盘点一下结构体标签在 Go 中的应用

盘点一下结构体标签在 Go 中的应用

2021-11-02 23:46网管叨bi叨KevinYan11 Golang

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

盘点一下结构体标签在 Go 中的应用

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

  1. typeUserstruct{
  2. Namestring`json:"name"`
  3. }

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

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

结构体标签

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

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

使用规范

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

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

  1. typeUserstruct{
  2. Namestring`json:"name"xml:"name"`
  3. }

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

  1. Namestring`json:"name,omitempty"`

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

  1. Namestring`json:"-"`

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

怎么获取到结构体标签

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

  1. typeStructFieldstruct{
  2. Namestring
  3. TypeType//fieldtype
  4. TagStructTag//fieldtagstring
  5. ......
  6. }

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

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

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

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

  1. func(tagStructTag)Get(keystring)string

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

  1. func(tagStructTag)Lookup(keystring)(valuestring,okbool)

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

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

  1. packagemain
  2. import(
  3. "fmt"
  4. "reflect"
  5. )
  6. typeUserstruct{
  7. Namestring`mytag:"MyName"`
  8. Emailstring`mytag:"MyEmail"`
  9. }
  10. funcmain(){
  11. u:=User{"Bob","bob@mycompany.com"}
  12. t:=reflect.TypeOf(u)
  13. fori:=0;i
  14. field:=t.Field(i)
  15. fmt.Printf("Field:User.%s\n",field.Name)
  16. fmt.Printf("\tWholetagvalue:%s\n",field.Tag)
  17. fmt.Printf("\tValueof'mytag':%s\n",field.Tag.Get("mytag"))
  18. }
  19. }

上面的程序会输出

  1. Field:User.Name
  2. Wholetagvalue:mytag:"MyName"
  3. Valueof'mytag':MyName
  4. Field:User.Email
  5. Wholetagvalue:mytag:"MyEmail"
  6. Valueof'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://mp.weixin.qq.com/s/1AVL5k9D55fWIkWm4UPR0Q

延伸 · 阅读

精彩推荐
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27