這篇文章主要想分享一下Go的struct宣告允許欄位附帶Tag來對欄位做一些標記究竟有什麼作用,是用來幹嘛的,開始步入正題。
struct中欄位的Tag不僅僅是一個字串那麼簡單,因為其主要用於反射場景,reflect包中提供了操作Tag 的方法,所以Tag 寫法也要遵循一定的規則。
- Tag規則
- Tag本身是一個字串,但字串中卻是,以空格分隔的key:value 對 。
- key:必須是非空字串,字串不能包含控制字元、空格、引號、冒號。
- value:以雙引號標記的字串
- 注意:冒號前後不能有空格
- 如下程式碼所示,如此寫沒有實際意義,僅用於說明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 協議》,轉載必須註明作者和本文連結