喜歡本站的朋友可以收藏本站,或者加入QQ群:172816590Web網頁設計師,我們大家一起來交流技術!

歡迎來到梁鍾霖個人博客網站。本 個人博客網站提供最新的站長新聞,各種互聯網資訊。 還提供個人博客模板,最新最全的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。