<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          盤點(diǎn)一下結(jié)構(gòu)體標(biāo)簽在 Go 中的應(yīng)用

          共 1984字,需瀏覽 4分鐘

           ·

          2021-11-29 10:11

          掌握了Go語(yǔ)言的朋友們應(yīng)該都知道,在Go的結(jié)構(gòu)體類型聲明里面,字段聲明后可以跟一個(gè)可選的字符串標(biāo)簽。

          type?User?struct?{
          ????Name?string?`json:"name"`
          }

          上面是一個(gè)標(biāo)準(zhǔn)的例子,Name字段聲明中指定了標(biāo)簽json:"name" xml:"name" ,這個(gè)標(biāo)簽值看著有點(diǎn)類似Java程序里給類屬性加的注解。

          那么這些結(jié)構(gòu)體標(biāo)簽有什么用途呢,我們隨便寫(xiě)管用嗎?我們平時(shí)工作中常用的結(jié)構(gòu)體標(biāo)簽有哪些呢?我們能不能自己定義結(jié)構(gòu)體標(biāo)簽?今天就帶大家掰扯清楚這些問(wèn)題!

          結(jié)構(gòu)體標(biāo)簽

          Go語(yǔ)言允許我們通過(guò)結(jié)構(gòu)體字段標(biāo)簽給一個(gè)字段附加可以被反射獲取的”元信息“,正好我們上篇文章實(shí)戰(zhàn)演示Go反射的使用方法和應(yīng)用場(chǎng)景中講了Go語(yǔ)言反射使用方法相關(guān)的內(nèi)容,對(duì)反射不清楚的可以先去再?gòu)?fù)習(xí)一下。

          通常情況下,結(jié)構(gòu)體標(biāo)簽被用于提供結(jié)構(gòu)體字段如何被編碼為或者解碼自另外一種格式的轉(zhuǎn)換信息(或者是以何種形式被保存至/獲取自數(shù)據(jù)庫(kù))。不過(guò),你也可以用它存儲(chǔ)任何你想要設(shè)置的”元信息“,供其他包或者自己使用。

          使用規(guī)范

          結(jié)構(gòu)體標(biāo)簽在使用上通常是遵守下面三個(gè)規(guī)范。

          結(jié)構(gòu)體標(biāo)簽字符串的值是一個(gè)由空格分隔的 key:"value" 對(duì)列表,例如:

          type?User?struct?{
          ????Name?string?`json:"name"?xml:"name"`
          }

          鍵,通常表示后面跟的“值”是被哪個(gè)包使用的,例如json這個(gè)鍵會(huì)被encoding/json包處理使用。如果要在“鍵”對(duì)應(yīng)的“值”中傳遞多個(gè)信息,通常通過(guò)用逗號(hào)(',')分隔來(lái)指定,例如

          Name?string?`json:"name,omitempty"`

          按照慣例,如果一個(gè)字段的結(jié)構(gòu)體標(biāo)簽里某個(gè)鍵的“值”被設(shè)置成了的破折號(hào) ('-'),那么就意味著告訴處理該結(jié)構(gòu)體標(biāo)簽鍵值的進(jìn)程排除該字段。例如,把一個(gè)字段的標(biāo)簽設(shè)置成下面這樣

          Name?string?`json:"-"`

          就以為進(jìn)行JSON編碼/解碼時(shí)忽略Name這個(gè)字段。

          怎么獲取到結(jié)構(gòu)體標(biāo)簽

          從一開(kāi)始我們就說(shuō)結(jié)構(gòu)體標(biāo)簽是給反射準(zhǔn)備的,那么怎么在Go程序里用反射獲得到字段的結(jié)構(gòu)體標(biāo)簽?zāi)??看了我們上一篇文章的同學(xué),應(yīng)該會(huì)知道,結(jié)構(gòu)體字段類型相關(guān)的信息,在反射的世界里使用reflect.StructFiled這個(gè)類型表示的。

          type?StructField?struct?{
          ?Name?string
          ?Type??????Type??????//?field?type
          ?Tag???????StructTag?//?field?tag?string
          ??......
          }

          如上所示,其中包含的Tag字段即代表了字段聲明中的結(jié)構(gòu)體標(biāo)簽信息。讓我們通過(guò)自定義結(jié)構(gòu)體標(biāo)簽的例子來(lái)演示一下怎么使用它在反射里讀取到標(biāo)簽里的信息。

          用反射獲取到自定義的結(jié)構(gòu)體標(biāo)簽

          使用反射reflect包訪問(wèn)結(jié)構(gòu)體字段的標(biāo)簽值,我們需要先獲取到結(jié)構(gòu)體的類型信息Type,然后使用Type.Field(i int)Type.FieldByName(name string),方法查詢字段信息,這兩個(gè)方法都會(huì)返回一個(gè)StructField類型的值,上面我們也說(shuō)了它在反射的世界里用于描述一個(gè)結(jié)構(gòu)體字段;而StructField.Tag 是一個(gè)StructTag 類型的值,它描述了字段的標(biāo)簽。

          上面我們談到了結(jié)構(gòu)體標(biāo)簽的使用規(guī)范,如果遵循規(guī)范給字段設(shè)置了標(biāo)簽后,就可以使用StructTagGet方法解析標(biāo)簽的值并返回你指定的鍵的“值”。

          func?(tag?StructTag)?Get(key?string)?string

          為了方便判斷一個(gè)給定的key是否存在與標(biāo)簽中,StructTag還提供了一個(gè)Lookup方法

          func?(tag?StructTag)?Lookup(key?string)?(value?string,?ok?bool)

          Get方法不同的是,Lookup會(huì)通過(guò)返回的ok值告知給定key是否存在與標(biāo)簽中。

          下面通過(guò)一個(gè)例子,演示下獲取我們自定義標(biāo)簽的過(guò)程。

          package?main

          import?(
          ?"fmt"
          ?"reflect"
          )

          type?User?struct?{
          ?Name??string?`mytag:"MyName"`
          ?Email?string?`mytag:"MyEmail"`
          }



          func?main()?{
          ?u?:=?User{"Bob",?"[email protected]"}
          ?t?:=?reflect.TypeOf(u)

          ?for?i?:=?0;?i???field?:=?t.Field(i)
          ??fmt.Printf("Field:?User.%s\n",?field.Name)
          ??fmt.Printf("\tWhole?tag?value?:?%s\n",?field.Tag)
          ??fmt.Printf("\tValue?of?'mytag':?%s\n",?field.Tag.Get("mytag"))
          ?}
          }

          上面的程序會(huì)輸出

          Field:?User.Name
          ????????Whole?tag?value?:?mytag:"MyName"
          ????????Value?of?'mytag':?MyName
          Field:?User.Email
          ????????Whole?tag?value?:?mytag:"MyEmail"
          ????????Value?of?'mytag':?MyEmail

          常用的結(jié)構(gòu)體標(biāo)簽鍵

          常用的結(jié)構(gòu)體標(biāo)簽Key,指的是那些被一些常用的開(kāi)源包聲明使用的結(jié)構(gòu)體標(biāo)簽鍵。在這里總結(jié)了一些,都是一些我們平時(shí)會(huì)用到的包,它們是:

          • json: ?由encoding/json 包使用,詳見(jiàn)json.Marshal()的使用方法和實(shí)現(xiàn)邏輯。
          • xml : ?由encoding/xml包使用,詳見(jiàn)xml.Marshal()。
          • bson: ?由gobson包,和mongo-go包使用。
          • protobuf: ?由github.com/golang/protobuf/proto 使用,在包文檔中有詳細(xì)說(shuō)明。
          • yaml: ?由gopkg.in/yaml.v2 包使用,詳見(jiàn)yaml.Marshal()。
          • gorm: ?由gorm.io/gorm包使用,示例可以在GORM的文檔中找到。

          當(dāng)然這里列的就是最常用的幾個(gè)庫(kù)他們提供給我們使用的結(jié)構(gòu)體標(biāo)簽,歡迎大伙踴躍留言,補(bǔ)充一些自己平時(shí)用過(guò)的庫(kù)提供給開(kāi)發(fā)者使用的結(jié)構(gòu)體標(biāo)簽

          總結(jié)

          這篇文章算是我們上一篇講Go反射的一個(gè)實(shí)踐方向的延伸介紹,如果你也想在自己的包里提供一些結(jié)構(gòu)體標(biāo)簽鍵,讓自己的包更易用些,除了看咱們這篇文章外,還可以去看看上面咱們介紹的幾個(gè)類庫(kù),看它們的源碼里是怎么應(yīng)用的,現(xiàn)學(xué)現(xiàn)用!

          相關(guān)文章

          - END -


          掃碼關(guān)注公眾號(hào)「網(wǎng)管叨bi叨」

          給網(wǎng)管個(gè)星標(biāo),第一時(shí)間吸我的知識(shí)???

          網(wǎng)管為大家整理了一本超實(shí)用的《Go 開(kāi)發(fā)參考書(shū)》收集了70多條開(kāi)發(fā)實(shí)踐。去公眾號(hào)回復(fù)【gocookbook】即刻領(lǐng)??!


          覺(jué)得有用就點(diǎn)個(gè)在看? ??????

          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲天堂一区 | 性猛交XXXX乱大交孕妇 | 99视频在线观看中文字幕 | 大雞巴弄得我好舒服黃片动漫版 | 国产又爽又黄无遮挡 |