自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go 語言中結(jié)構(gòu)體打 Tag 是什么意思?

開發(fā) 后端
哈嘍,大家好,我是asong。今天想與大家分享Go語言中結(jié)構(gòu)體標(biāo)簽是怎么使用的,以及怎樣定制自己的結(jié)構(gòu)體標(biāo)簽解析。

[[434972]]

前言

哈嘍,大家好,我是asong。今天想與大家分享Go語言中結(jié)構(gòu)體標(biāo)簽是怎么使用的,以及怎樣定制自己的結(jié)構(gòu)體標(biāo)簽解析。

大多數(shù)初學(xué)者在看公司的項(xiàng)目代碼時,看到的一些結(jié)構(gòu)體定義會是這樣的:

  1. type Location struct { 
  2.  Longitude float32 `json:"lon,omitempty"
  3.  Latitude  float32 `json:"lat,omitempty"

字段后面會有一個標(biāo)簽,這個標(biāo)簽有什么用呢?

上面的例子中,標(biāo)簽json:"lon,omitempty"代表的意思是結(jié)構(gòu)體字段的值編碼為json對象時,每一個導(dǎo)出字段變成該對象的一個成員,這個成員的名字為lon或者lat,并且當(dāng)字段是空值時,不導(dǎo)出該字段;總結(jié)就是lon、lat是重命名成員的名字,omitempty用來決定成員是否導(dǎo)出。

看到這里,有一些朋友可能會好奇,這個你是怎么知道這樣使用的呢?我可以隨便寫標(biāo)簽嗎?

接下來我們就一點(diǎn)點(diǎn)來揭秘,開車!!!

什么是標(biāo)簽

Go語言提供了可通過反射發(fā)現(xiàn)的的結(jié)構(gòu)體標(biāo)簽,這些在標(biāo)準(zhǔn)庫json/xml中得到了廣泛的使用,orm框架也支持了結(jié)構(gòu)體標(biāo)簽,上面那個例子的使用就是因?yàn)閑ncoding/json支持了結(jié)構(gòu)體標(biāo)簽,不過他有自己的標(biāo)簽規(guī)則;但是他們都有一個總體規(guī)則,這個規(guī)則是不能更改的,具體格式如下:

  1. `key1:"value1" key2:"value2" key3:"value3"...` // 鍵值對用空格分隔 

結(jié)構(gòu)體標(biāo)簽可以有多個鍵值對,鍵與值要用冒號分隔,值要使用雙引號括起來,多個鍵值對之間要使用一個空格分隔,千萬不要使用逗號!!!

如果我們想要在一個值中傳遞多個信息怎么辦?不同庫中實(shí)現(xiàn)的是不一樣的,在encoding/json中,多值使用逗號分隔:

  1. `json:"lon,omitempty"

在gorm中,多值使用分號分隔:

  1. `gorm:"column:id;primaryKey" 

具體使用什么符號分隔需要大家要看各自庫的文檔獲取。

結(jié)構(gòu)體標(biāo)簽是在編譯階段就和成員進(jìn)行關(guān)聯(lián)的,以字符串的形式進(jìn)行關(guān)聯(lián),在運(yùn)行階段可以通過反射讀取出來。

現(xiàn)在大家已經(jīng)知道什么是結(jié)構(gòu)體標(biāo)簽了,規(guī)則還是很規(guī)范的,但是很容易出錯,因?yàn)镚o語言在編譯階段并不會對其格式做合法鍵值對的檢查,這樣我們不小心寫錯了,就很難被發(fā)現(xiàn),不過我們有g(shù)o vet工具做檢查,具體使用來看一個例子:

  1. type User struct { 
  2.  Name string `abc def ghk` 
  3.  Age uint16 `123: 232` 
  4. func main()  { 

然后執(zhí)行g(shù)o vet main.go,得出執(zhí)行結(jié)果:

  1. # command-line-arguments 
  2. go_vet_tag/main.go:4:2: struct field tag `abc def ghk` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair 
  3. go_vet_tag/main.go:5:2: struct field tag `123: 232` not compatible with reflect.StructTag.Get: bad syntax for struct tag value 

bad syntax for struct tag pair告訴我們鍵值對語法錯誤,bad syntax for struct tag value值語法錯誤。

所以在我們項(xiàng)目中引入go vet作為CI檢查是很有必要的。

標(biāo)簽使用場景

Go官方已經(jīng)幫忙整理了哪些庫已經(jīng)支持了struct tag:https://github.com/golang/go/wiki/Well-known-struct-tags。

Tag Documentation
xml https://godoc.org/encoding/xml
json https://godoc.org/encoding/json
asn1 https://godoc.org/encoding/asn1
reform https://godoc.org/gopkg.in/reform.v1
dynamodb https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/#Marshal
bigquery https://godoc.org/cloud.google.com/go/bigquery
datastore https://godoc.org/cloud.google.com/go/datastore
spanner https://godoc.org/cloud.google.com/go/spanner
bson https://godoc.org/labix.org/v2/mgo/bson, https://godoc.org/go.mongodb.org/mongo-driver/bson/bsoncodec
gorm https://godoc.org/github.com/jinzhu/gorm
yaml https://godoc.org/gopkg.in/yaml.v2
toml https://godoc.org/github.com/pelletier/go-toml
validate https://github.com/go-playground/validator
mapstructure https://godoc.org/github.com/mitchellh/mapstructure
parser https://godoc.org/github.com/alecthomas/participle
protobuf https://github.com/golang/protobuf
db https://github.com/jmoiron/sqlx
url https://github.com/google/go-querystring
feature https://github.com/nikolaydubina/go-featureprocessing

像json、yaml、gorm、validate、mapstructure、protobuf這幾個庫的結(jié)構(gòu)體標(biāo)簽是很常用的,gin框架就集成了validate庫用來做參數(shù)校驗(yàn),方便了許多,之前寫了一篇關(guān)于validate的文章:boss: 這小子還不會使用validator庫進(jìn)行數(shù)據(jù)校驗(yàn),開了~~~,可以關(guān)注一下。

具體這些庫中是怎么使用的,大家可以看官方文檔介紹,寫的都很詳細(xì),具體場景具體使用哈!!!

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

現(xiàn)在我們可以回答開頭的一個問題了,結(jié)構(gòu)體標(biāo)簽是可以隨意寫的,只要符合語法規(guī)則,任意寫都可以的,但是一些庫沒有支持該標(biāo)簽的情況下,隨意寫的標(biāo)簽是沒有任何意義的,如果想要我們的標(biāo)簽變得有意義,就需要我們提供解析方法??梢酝ㄟ^反射的方式獲取標(biāo)簽,所以我們就來看一個例子,如何使用反射獲取到自定義的結(jié)構(gòu)體標(biāo)簽。

  1. type User struct { 
  2.  Name string `asong:"Username"
  3.  Age  uint16 `asong:"age"
  4.  Password string `asong:"min=6,max=10"
  5. func getTag(u User) { 
  6.  t := reflect.TypeOf(u) 
  7.  
  8.  for i := 0; i < t.NumField(); i++ { 
  9.   field := t.Field(i) 
  10.   tag := field.Tag.Get("asong"
  11.   fmt.Println("get tag is ", tag) 
  12.  } 
  13.  
  14. func main()  { 
  15.  u := User
  16.   Name"asong"
  17.   Age: 5, 
  18.   Password"123456"
  19.  } 
  20.  getTag(u) 

運(yùn)行結(jié)果如下:

  1. get tag is  Username 
  2. get tag is  age 
  3. get tag is  min=6,max=10 

這里我們使用TypeOf方法獲取的結(jié)構(gòu)體類型,然后去遍歷字段,每個字段StructField都有成員變量Tag:

  1. // A StructField describes a single field in a struct. 
  2. type StructField struct { 
  3.  Name string 
  4.  PkgPath string 
  5.  Type      Type      // field type 
  6.  Tag       StructTag // field tag string 
  7.  Offset    uintptr   // offset within struct, in bytes 
  8.  Index     []int     // index sequence for Type.FieldByIndex 
  9.  Anonymous bool      // is an embedded field 

Tag是一個內(nèi)置類型,提供了Get、Loopup兩種方法來解析標(biāo)簽中的值并返回指定鍵的值:

  1. func (tag StructTag) Get(key string) string 
  2.  
  3. func (tag StructTag) Lookup(key string) (value string, ok bool) 

Get內(nèi)部也是調(diào)用的Lookup方法。區(qū)別在于Lookup會通過返回值告知給定key是否存在與標(biāo)簽中,Get方法完全忽略了這個判斷。

總結(jié)

本文主要介紹一下Go語言中的結(jié)構(gòu)體標(biāo)簽是什么,以及如何使用反射獲取到解結(jié)構(gòu)體標(biāo)簽,在日常開發(fā)中我們更多的是使用一些庫提供好的標(biāo)簽,很少自己開發(fā)使用,不過大家有興趣的話可以讀一下validae的源碼,看看他是如何解析結(jié)構(gòu)體中的tag,也可以自己動手實(shí)現(xiàn)一個校驗(yàn)庫,當(dāng)作練手項(xiàng)目。

 

文中代碼已上傳github:https://github.com/asong2020/Golang_Dream/tree/master/code_demo/struct_tag_demo

 

責(zé)任編輯:武曉燕 來源: Golang夢工廠
相關(guān)推薦

2023-07-29 15:03:29

2023-01-12 08:52:50

GoroutinesGo語言

2020-10-14 07:50:57

DNS劫持

2021-04-20 09:00:48

Go 語言結(jié)構(gòu)體type

2020-07-21 15:20:20

語言結(jié)構(gòu)體共用體

2018-10-08 15:42:37

VoLTE4G流量語音

2010-09-26 10:29:45

JVMJava虛擬機(jī)

2021-01-21 21:24:34

DevOps開發(fā)工具

2010-08-25 10:28:05

margin

2010-09-09 09:23:42

CSSDIV

2020-11-23 08:54:14

Go語言結(jié)構(gòu)體

2020-11-30 06:17:03

Go語言

2020-11-26 06:40:24

Go語言基礎(chǔ)

2020-12-02 08:45:36

Go語言

2022-08-26 09:51:49

索引簽名編程語言

2022-09-18 23:09:13

Go語言標(biāo)準(zhǔn)庫

2024-03-29 09:12:43

Go語言工具

2020-12-02 09:10:22

Go結(jié)構(gòu)數(shù)據(jù)類型

2013-01-18 15:25:27

無線網(wǎng)絡(luò)無線APWi-Fi

2014-07-28 08:28:38

Windows
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號