成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 語言中結構體打 Tag 是什么意思?

開發 后端
哈嘍,大家好,我是asong。今天想與大家分享Go語言中結構體標簽是怎么使用的,以及怎樣定制自己的結構體標簽解析。

[[434972]]

前言

哈嘍,大家好,我是asong。今天想與大家分享Go語言中結構體標簽是怎么使用的,以及怎樣定制自己的結構體標簽解析。

大多數初學者在看公司的項目代碼時,看到的一些結構體定義會是這樣的:

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

字段后面會有一個標簽,這個標簽有什么用呢?

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

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

接下來我們就一點點來揭秘,開車!!!

什么是標簽

Go語言提供了可通過反射發現的的結構體標簽,這些在標準庫json/xml中得到了廣泛的使用,orm框架也支持了結構體標簽,上面那個例子的使用就是因為encoding/json支持了結構體標簽,不過他有自己的標簽規則;但是他們都有一個總體規則,這個規則是不能更改的,具體格式如下:

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

結構體標簽可以有多個鍵值對,鍵與值要用冒號分隔,值要使用雙引號括起來,多個鍵值對之間要使用一個空格分隔,千萬不要使用逗號!!!

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

  1. `json:"lon,omitempty"

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

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

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

結構體標簽是在編譯階段就和成員進行關聯的,以字符串的形式進行關聯,在運行階段可以通過反射讀取出來。

現在大家已經知道什么是結構體標簽了,規則還是很規范的,但是很容易出錯,因為Go語言在編譯階段并不會對其格式做合法鍵值對的檢查,這樣我們不小心寫錯了,就很難被發現,不過我們有go vet工具做檢查,具體使用來看一個例子:

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

然后執行go vet main.go,得出執行結果:

  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值語法錯誤。

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

標簽使用場景

Go官方已經幫忙整理了哪些庫已經支持了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這幾個庫的結構體標簽是很常用的,gin框架就集成了validate庫用來做參數校驗,方便了許多,之前寫了一篇關于validate的文章:boss: 這小子還不會使用validator庫進行數據校驗,開了~~~,可以關注一下。

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

自定義結構體標簽

現在我們可以回答開頭的一個問題了,結構體標簽是可以隨意寫的,只要符合語法規則,任意寫都可以的,但是一些庫沒有支持該標簽的情況下,隨意寫的標簽是沒有任何意義的,如果想要我們的標簽變得有意義,就需要我們提供解析方法。可以通過反射的方式獲取標簽,所以我們就來看一個例子,如何使用反射獲取到自定義的結構體標簽。

  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) 

運行結果如下:

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

這里我們使用TypeOf方法獲取的結構體類型,然后去遍歷字段,每個字段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是一個內置類型,提供了Get、Loopup兩種方法來解析標簽中的值并返回指定鍵的值:

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

Get內部也是調用的Lookup方法。區別在于Lookup會通過返回值告知給定key是否存在與標簽中,Get方法完全忽略了這個判斷。

總結

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

 

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

 

責任編輯:武曉燕 來源: Golang夢工廠
相關推薦

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 語言結構體type

2020-07-21 15:20:20

語言結構體共用體

2010-09-26 10:29:45

JVMJava虛擬機

2021-01-21 21:24:34

DevOps開發工具

2010-09-09 09:23:42

CSSDIV

2010-08-25 10:28:05

margin

2020-12-02 08:45:36

Go語言

2020-11-30 06:17:03

Go語言

2020-11-26 06:40:24

Go語言基礎

2020-11-23 08:54:14

Go語言結構體

2018-10-08 15:42:37

VoLTE4G流量語音

2022-08-26 09:51:49

索引簽名編程語言

2022-09-18 23:09:13

Go語言標準庫

2020-12-02 09:10:22

Go結構數據類型

2024-04-07 11:33:02

Go逃逸分析

2021-07-15 23:18:48

Go語言并發

2024-03-29 09:12:43

Go語言工具
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天操人人干 | 龙珠z在线观看 | 99re在线视频免费观看 | 在线观看视频91 | 久久久一二三 | 最新中文在线视频 | 亚洲激情在线观看 | 欧美视频福利 | 拍真实国产伦偷精品 | 久久夜视频 | 亚洲劲爆av| 国产综合视频 | 美女爽到呻吟久久久久 | 国产福利在线播放麻豆 | 91精品国产91久久久久久最新 | 久艹av | 亚洲精品无 | 久久精品一区二区 | 日韩网站在线观看 | 天天天久久久 | 国产精品免费在线 | 国产精品久久久久国产a级 欧美日韩国产免费 | 99久久久久久99国产精品免 | 在线观看国产www | 成人免费大片黄在线播放 | 精品一区二区久久久久久久网精 | 噜噜噜噜狠狠狠7777视频 | 蜜臀久久99精品久久久久野外 | 午夜影院网站 | 亚洲精品一区中文字幕 | 国内精品久久久久久 | 亚洲一区二区视频 | 精品1区2区| jizz在线免费观看 | 亚洲精品粉嫩美女一区 | 老司机成人在线 | 毛色毛片免费看 | www.免费看片.com| 久久精品中文 | 艹逼网| 日韩精品无码一区二区三区 |