Golang的Tag文法

來源:互聯網
上載者:User

我們可以通過Tag來增強結構體的定義,Tag會帶上一些meta資訊,在本文中我們將通過幾個例子來深入瞭解Tag的用法。

結構

Struct是由一組field組成,每個field包括了名字(可選)和欄位類型

package mainimport "fmt"type T1 struct {    f1 string}type T2 struct {    T1    f2     int64    f3, f4 float64}func main() {    t := T2{T1{"foo"}, 1, 2, 3}    fmt.Println(t.f1)    // foo    fmt.Println(t.T1.f1) // foo    fmt.Println(t.f2)    // 1}

field T1是一個嵌入型field, 它並沒有欄位名 。Field定義可以像f3f4一樣公用一個欄位類型。

標籤

有時候會在欄位定義後面帶上一個字串(tag)。類似於如下

type T struct {    f1     string "f one"    f2     string    f3     string `f three`    f4, f5 int64  `f four and five`}

不管是raw string還是interpreted string都可以用來當tag。 如果field定義時候兩個名字公用一個屬性,那麼這個tag會被附在兩個名字上,像f4,f5一樣。

反射

Tag在運行時可以通過reflection包來讀取

package mainimport (    "fmt"    "reflect")type T struct {    f1     string "f one"    f2     string    f3     string `f three`    f4, f5 int64  `f four and five`}func main() {    t := reflect.TypeOf(T{})    f1, _ := t.FieldByName("f1")    fmt.Println(f1.Tag) // f one    f4, _ := t.FieldByName("f4")    fmt.Println(f4.Tag) // f four and five    f5, _ := t.FieldByName("f5")    fmt.Println(f5.Tag) // f four and five}

設定一個空tag和不設定tag的效果一致

type T struct {    f1 string ``    f2 string}func main() {    t := reflect.TypeOf(T{})    f1, _ := t.FieldByName("f1")    fmt.Printf("%q\n", f1.Tag) // ""    f2, _ := t.FieldByName("f2")    fmt.Printf("%q\n", f2.Tag) // ""}

格式

Tags可以由索引值對來組成,通過空格符來分割索引值 —key1:"value1" key2:"value2" key3:"value3"。如果Tags格式沒問題的話,我們可以通過Lookup或者Get來擷取索引值對的值。
Lookup回傳兩個值 —對應的值和是否找到

type T struct {    f string `one:"1" two:"2"blank:""`}func main() {    t := reflect.TypeOf(T{})    f, _ := t.FieldByName("f")    fmt.Println(f.Tag) // one:"1" two:"2"blank:""    v, ok := f.Tag.Lookup("one")    fmt.Printf("%s, %t\n", v, ok) // 1, true    v, ok = f.Tag.Lookup("blank")    fmt.Printf("%s, %t\n", v, ok) // , true    v, ok = f.Tag.Lookup("five")    fmt.Printf("%s, %t\n", v, ok) // , false}

Get方法只是簡單的封裝了以下Lookup。但是丟棄了是否成功結果

func (tag StructTag) Get(key string) string {    v, _ := tag.Lookup(key)    return v}

轉化

將結構體的值轉化成其他的類型可通過Tag來定義

type T1 struct {     f int `json:"foo"` } type T2 struct {     f int `json:"bar"` } t1 := T1{10} var t2 T2 t2 = T2(t1) fmt.Println(t2) // {10}

什麼時候用到了Tag

(Un)marshaling

Tag最常用的大概就是在marshaling

import (    "encoding/json"    "fmt")func main() {    type T struct {       F1 int `json:"f_1"`       F2 int `json:"f_2,omitempty"`       F3 int `json:"f_3,omitempty"`       F4 int `json:"-"`    }    t := T{1, 0, 2, 3}    b, err := json.Marshal(t)    if err != nil {        panic(err)    }    fmt.Printf("%s\n", b) // {"f_1":1,"f_3":2}}

ORM

比如說GORM— example.

go vet

go的編譯器不會強行要求你使用合理的tags。但是 go vet可以檢查出你的tag是否合理。

package maintype T struct {    f string "one two three"}func main() {}> go vet tags.gotags.go:4: struct field tag `one two three` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.