go中Tag的理解与使用

这篇文章主要想分享一下Go的struct声明允许字段附带Tag来对字段做一些标记究竟有什么作用,是用来干嘛的,开始步入正题。

struct中字段的Tag不仅仅是一个字符串那么简单,因为其主要用于反射场景,reflect包中提供了操作Tag 的方法,所以Tag 写法也要遵循一定的规则。

  • Tag规则
    1. Tag本身是一个字符串,但字符串中却是,以空格分隔的key:value 对 。
    2. key:必须是非空字符串,字符串不能包含控制字符、空格、引号、冒号。
    3. value:以双引号标记的字符串
    4. 注意:冒号前后不能有空格
    5. 如下代码所示,如此写没有实际意义,仅用于说明Tag规则是咋样的,ServerName 字段的Tag包含两个key-value对。ServerIP字段的Tag只包含一个key-value对。:
      type Server struct {
      ServerName string `key1: "value1" key11:"value11"`
      ServerIP string `key2: "value2"`
      }

必须要理解的是Tag是Struct的一部分,前面说过Tag只有在反射场景中才有用,而反射包中提供了操作Tag的方法,在说方法前,有必要先了解一下Go是如何管理struct字段的。

  • 以下是reflect 包中的类型声明,省略了部分与无关的字段:
    type StructField struct {
       Name string
       Type Type
       Tag StructTag
    }
    type StructTag string
  • 如上可见,描述一个结构体成员的结构中包含了StructTag,而其本身是一个 string,也就是说Tag其实是结构体字段的一个组成部分。

下面说一下如何获取Tag
StructTag提供了Get(key string)string方法来获取Tag,示例如下:

func main() {
    s := Server{}
    st := reflect.TypeOf(s)
    field1 := st.Field(0)
    fmt.Printf("key1:%v\n",field1.Tag.Get("key1"))
    fmt.Printf("key11:%v\n",field1.Tag.Get("key11"))
    filed2 := st.Field(1)
    fmt.Printf("key2:%v\n",filed2.Tag.Get("key2"))
}
//程序输出如下:
key1:value1
key11:value11
key2:value2

最后讲一下Tag存在的意义与常见用法

  • 注意:本文示例中tag没有任何实际意义,只是为了阐述tag的定义与操作方法而已。
  • 在使用反射可以动态的给结构体成员赋值,正是因为有tag,在赋值前可以使用tag来决定赋值的动作。比如,官方的encoding/json 包,可以将一个JSON数据Unmarshal 进一个结构体,此过程中就使用了Tag,该包定义一些规则,只要参考该规则设置tag就可以将不同的JSON数据转换成结构体。
  • 基于struct的tag特性,有了诸如json、orm等等的应用。理解这个可以定义另一种tag规则,来处理特有的数据。

Tag的内容我所理解和了解的只有这么多了,还有更多玩法的欢迎留言评论告知

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!