首页 > 编程笔记 > Go语言笔记 阅读:23

Go语言结构体标签(Tag)详解(附带实例)

在一般情况下,Go 语言定义的结构体中,每个字段都是由字段名称和字段类型构成的。

例如,在定义的 Book 类型的结构体中,包含两个字段:
代码如下:
type Book struct { //定义的 Book 类型的结构体
    BookName string //表示图书名称的 string 类型 BookName
    BookPrice float64 //表示图书价格的 float64 类型 BookPrice
}

结构体标签的使用

除了字段名称和字段类型,还可以为每个字段增加一个属性,即“结构体标签(Tag)”。

结构体标签是一系列用空格分隔的键值对序列,用英文格式下的反引号(即``)括起来。结构体标签的语法格式如下:
`key:"value" key2:"value2" key3:"value3"`
结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔。

下面为上面定义的 Book 类型的结构体中的两个字段增加标签。代码如下:
type Book struct {
    BookName string `json:"BookName"`
    bookPrice float64 `json:"bookPrice"`
}
当键为 json 时,这个键对应的值不仅能控制 encoding/json 包的编码和解码的行为,还能控制 encoding 下的其他包的编码和解码的行为。

下面通过示例演示如何使用为字段增加标签的结构体编码 JSON。代码如下:
package main

import (
    "encoding/json"
    "fmt"
)

type Book struct {
    BookName string `json:"name"`
    BookPrice float64 `json:"price"`
}

func main() {
    book := Book{
        BookName: "C语言入门教程",
        BookPrice: 49.90,
    }
    res, := json.Marshal(book) //结构体转为 JSON
    fmt.Printf("res:%s\n", res) //打印 JSON
}
运行结果如下:
res:{"name":"C语言入门教程","price":49.4}

Go语言结构体标签的获取

在开发过程中,如何获取结构体标签呢?使用反射是关键。

Go 语言支持 3 种获取结构体标签的方式,分别是获取字段信息、获取结构体标签和获取键值对。

1) 获取字段信息

Go语言同样有 3 种获取字段信息的方式。这 3 种方式的语法格式如下:
field := reflect.TypeOf(obj).FieldByName("Name") //表示第几个字段
field := reflect.ValueOf(obj).Type().Field(i) //表示第几个字段
field := reflect.ValueOf(&obj).Elem().Type().Field(i) //表示第几个字段

2) 获取结构体标签

Go 语言获取结构体标签的语法格式如下:
tag := field.Tag

3) 获取键值对

Go 语言有两种获取键值对的方式,语法格式如下:
labelValue:= tag.Get("label") //当没有获取到对应的结构体标签时,Get()函数返回空字符串
labelValue, ok := tag.Lookup("label")

下面演示如何获取结构体标签和键值对。代码如下:
package main

import (
    "fmt"
    "reflect"
)

type Book struct {
    BookName string `json:"name"`
    BookPrice float64 `json:"price"`
}

func main() {
    book := reflect.TypeOf(Book{}) //创建结构体 Book{}的反射对象
    nm, _ := book.FieldByName("BookName") //获取字段 BookName 的信息
    fmt.Println("字段 BookName 的信息:\n", nm) //获取字段 BookName 对应的结构体标签
    tag := nm.Tag //获取与字段 BookName 对应的结构体标签
    fmt.Println("与字段 BookName 对应的结构体标签:\n", tag)
    value, _ = tag.Lookup("json") //获取与字段 BookName 对应的结构体标签中的键值对
    fmt.Println("与字段 BookName 对应的结构体标签中的键值对:\n key: json, value:", value)
}
运行结果如下:
字段 BookName 的信息:
(BookName string json:"name" 0 [0] false)
与字段 BookName 对应的结构体标签:
json:"name"
与字段 BookName 对应的结构体标签中的键值对:
key: json, value: name
在上述运行结果中,字段 BookName 的信息比较复杂。字段 BookName 的信息表示的是字段 BookName 与结构体 Book{} 的关系,如偏移、索引、是否为匿名字段、结构体标签等。

为了深入探究结构体成员的信息,要理解 Go 语言提供的结构体成员的语法格式,即:
type StructField struct {
    Name     string //字段名
    PkgPath string //字段在结构体中的路径
    Type    Type //字段的反射类型对象
    Tag     StructTag //字段的结构体标签
    Offset   uintptr //字段在结构体中的相对偏移
    Index    []int //字段对应的索引值
    Anonymous bool //是否为匿名字段
}

相关文章