Go struct tag深入理解
歡迎來到梁鍾霖個人博客網站。本 個人博客網站提供最新的站長新聞,各種互聯網資訊。 還提供個人博客模板,最新最全的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映射。 后面再單獨介紹。