喜欢本站的朋友可以收藏本站,或者加入QQ群:172816590技术图片,我们大家一起来交流技术!

欢迎来到梁钟霖个人博客网站。本个人博客网站提供最新的站长新闻,各种互联网资讯。 还提供个人博客模板,最新最全的java教程,java面试题。在此我将尽我最大所能将此个人博客网站做的最好! 谢谢大家,愿大家一起进步! 

Go的struct声明允许字段附带Tag来对字段做一些标记。
Tag不仅仅是一个字符串那么简单,因为其主要用于反射场景,reflect包中提供了操作Tag的方法,所以Tag写法也要遵循一定的规则。

Tag的构成

Tag本身是一个字符串,但字符串中却是:以空格分隔的 key:value 对

  • key: 必须是非空字符串,字符串不能包含控制字符、空格、引号、冒号。
  • value: 以双引号标记的字符串
  • 注意:冒号前后不能有空格

如下代码所示,如此写没有实际意义,仅用于说明Tag规则

type Server struct {
    ServerName string `key1: "value1" key11:"value11"`
    ServerIP   string `key2: "value2"`
}

上述代码ServerName字段的Tag包含两个key-value对。ServerIP字段的Tag只包含一个key-value对。

Struct类型表示

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

以下是reflect包中的类型声明,省略了部分与本文无关的字段。

// A StructField describes a single field in a struct.
type StructField struct {
	// Name is the field name.
	Name string
	...
	Type      Type      // field type
	Tag       StructTag // field tag string
	...
}

type StructTag string

可见,描述一个结构体成员的结构中包含了StructTag,而其本身是一个string。也就是说Tag其实是结构体字段的一个组成部分。

使用反射获取Tag

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

package main

import (
    "reflect"
    "fmt"
)

type Server struct {
    ServerName string `key1:"value1" key11:"value11"`
    ServerIP   string `key2:"value2"`
}

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的定义与操作方法,也为了避免与你之前见过的诸如json:xxx混淆。
使用反射可以动态的给结构体成员赋值,正是因为有tag,在赋值前可以使用tag来决定赋值的动作。 比如,官方的encoding/json包,可以将一个JSON数据Unmarshal进一个结构体,此过程中就使用了Tag. 该包定义一些规则,只要参考该规则设置tag就可以将不同的JSON数据转换成结构体。

总之:正是基于struct的tag特性,才有了诸如json、orm等等的应用。理解这个关系是至关重要的。或许,你可以定义另一种tag规则,还处理你特有的数据。

Tag常见用法

常见的tag用法,主要是JSON数据解析、ORM映射。 后面再单独介绍。


 转载至链接:https://my.oschina.net/renhc/blog/2045683。