Go語(yǔ)言omitempty選項(xiàng)的實(shí)現(xiàn)
在使用Golang的時(shí)候,不免會(huì)使用Json和結(jié)構(gòu)體的相互轉(zhuǎn)換,這時(shí)候常用的就是 json.Marshal 和 json.Unmarshal 兩個(gè)函數(shù)。這時(shí)候在定義json結(jié)構(gòu)體的時(shí)候,我們會(huì)用到 omitempty 這個(gè)字段,這個(gè)字段作用就是 空值省略,看似簡(jiǎn)單,但是卻有很多小坑,這篇文章帶你稍微研究一下他的用途和功能。
omit:
v. 刪除; 忽略; 漏掉; 遺漏; 不做; 未能做;
adj. 省略了的;省去的;
基本用法
當(dāng)我們?cè)O(shè)置json的struct的時(shí)候,會(huì)定義每個(gè)字段對(duì)一個(gè)json的格式,比如定義一個(gè)dog 結(jié)構(gòu)體:
type Dog struct { Name string Weight int }
現(xiàn)在我們對(duì)他進(jìn)行初始化,將其編碼為JSON格式:
func main() { d := Dog{ Name: "小黑", Weight: 20, } marshalDog, err := json.Marshal(d) if err != nil { fmt.Println(err.Error()) } fmt.Println(string(marshalDog)) }
則輸出的結(jié)果為:
{"Name":"小黑","Weight":20}
現(xiàn)在假如有一個(gè)結(jié)構(gòu)體變量我們沒(méi)初始化,那么結(jié)果可能也會(huì)跟我們預(yù)期的不太一樣:
d := Dog{ Name: "小黑", }
輸出的結(jié)果為:
{"Name":"小黑","Weight":0}
很明顯,狗的weight是未知,而不是0,并不是我們想要的結(jié)果,我們更想要的結(jié)果是:
{"Name":"小黑"}
為了實(shí)現(xiàn)這樣的目的,我們這時(shí)候應(yīng)該使用 omitempty 選項(xiàng)來(lái)幫我們實(shí)現(xiàn),當(dāng)我們?cè)贒og結(jié)構(gòu)體加上這個(gè)tag的時(shí)候:
type Dog struct { Name string Weight int `json:",omitempty"` }
此時(shí),輸出結(jié)果為:
{"Name":"小黑"}
不能單純使用omitempty
當(dāng)結(jié)構(gòu)體相互嵌套的時(shí)候,那么omitempty就可能出現(xiàn)問(wèn)題,比如:
type Variety struct { ?? ?Color ? ?string ?? ?Category string } type Dog struct { ?? ?Name ? ?string ?? ?Weight ?int ? ? `json:",omitempty"` ?? ?Variety Variety `json:",omitempty"` } func main() { ?? ?d := Dog{ ?? ??? ?Name: "小黑", ?? ?} ?? ?marshalDog, err := json.Marshal(d) ?? ?if err != nil { ?? ??? ?fmt.Println(err.Error()) ?? ?} ?? ?fmt.Println(string(marshalDog)) }
輸出結(jié)果為:
{"Name":"小黑","Variety":{"Color":"","Category":""}}
omitempty 為什么對(duì)嵌套結(jié)構(gòu)體不生效呢?這是因?yàn)镚O只知道簡(jiǎn)單結(jié)構(gòu)體例如int,string,pointer 這種類(lèi)型的空值,不知道Variety類(lèi)型的空值是什么,為了不顯示我們沒(méi)有提供值的自定義結(jié)構(gòu)體,我們可以使用結(jié)構(gòu)體指針:
type Dog struct { Name string Weight int `json:",omitempty"` Variety *Variety `json:",omitempty"` }
運(yùn)行結(jié)果為:
{"Name":"小黑"}
但是如果給出下面情況的賦值:
d := Dog{ Name: "小黑", Variety: &Variety{Color: "black"}, }
運(yùn)行結(jié)果為:
{"Name":"小黑","Variety":{"Color":"black","Category":""}}
可以看到,omitempty只對(duì)*Variety生效。所以想要嵌套結(jié)構(gòu)體里面的字段也能有空值省略的效果,就要在定義嵌套的結(jié)構(gòu)體的時(shí)候,對(duì)里面的每個(gè)字段都要加上omitempty選項(xiàng)。如下所示:
type Variety struct { Color string `json:",omitempty"` Category string `json:",omitempty"` }
運(yùn)行結(jié)果如下:
{"Name":"小黑","Variety":{"Color":"black"}}
剩下的最后一個(gè)坑就是:如果想要某個(gè)值就是為空(有實(shí)際意義),也就是說(shuō)當(dāng)一個(gè)空值有實(shí)際意義的時(shí)候就顯示,沒(méi)有實(shí)際意義(當(dāng)時(shí)還不知道其值)的時(shí)候就不顯示,這樣的需求應(yīng)該怎么做?如果還是向上面那樣,當(dāng)我們需要Category為空的時(shí)候(Category:“”),最后會(huì)發(fā)現(xiàn)omitempty選項(xiàng)會(huì)把這個(gè)空值字段省略。正確的做法是使用指針來(lái)定義其變量。最后代碼如下:
package main import ( ?? ?"encoding/json" ?? ?"fmt" ) type Variety struct { ?? ?Color ? ?*string `json:",omitempty"` ?? ?Category *string `json:",omitempty"`//一定要是*string類(lèi)型 } type Dog struct { ?? ?Name ? ?string ?? ?Weight ?int ? ? ?`json:",omitempty"` ?? ?Variety *Variety `json:",omitempty"` } func main() { ?? ?color := "black" ? ? //此處的空值有實(shí)際意義 ?? ?category := "" ?? ?d := Dog{ ?? ??? ?Name: ? ?"小黑", ?? ??? ?Variety: &Variety{Color: &color, Category: &category}, ?? ?} ?? ?marshalDog, err := json.Marshal(d) ?? ?if err != nil { ?? ??? ?fmt.Println(err.Error()) ?? ?} ?? ?fmt.Println(string(marshalDog)) }
運(yùn)行結(jié)果如下:
{"Name":"小黑","Variety":{"Color":"black","Category":""}}
到此這篇關(guān)于Go語(yǔ)言omitempty選項(xiàng)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go語(yǔ)言omitempty選項(xiàng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言基礎(chǔ)學(xué)習(xí)之map的示例詳解
哈希表是常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),有的語(yǔ)言會(huì)將哈希稱作字典或者映射,在Go中,哈希就是常見(jiàn)的數(shù)據(jù)類(lèi)型map,本文就來(lái)聊聊Golang中map的相關(guān)知識(shí)吧2023-04-04Hugo 游樂(lè)場(chǎng)內(nèi)容初始化示例詳解
這篇文章主要為大家介紹了Hugo 游樂(lè)場(chǎng)內(nèi)容初始化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02golang語(yǔ)言中for循環(huán)語(yǔ)句用法實(shí)例
這篇文章主要介紹了golang語(yǔ)言中for循環(huán)語(yǔ)句用法,實(shí)例分析了for循環(huán)遍歷的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01簡(jiǎn)單高效!Go語(yǔ)言封裝二級(jí)認(rèn)證功能實(shí)現(xiàn)
本文將介紹如何使用Go語(yǔ)言封裝二級(jí)認(rèn)證功能,實(shí)現(xiàn)簡(jiǎn)單高效的用戶認(rèn)證流程,二級(jí)認(rèn)證是一種安全措施,要求用戶在登錄后進(jìn)行額外的身份驗(yàn)證,以提高賬戶安全性,2023-10-10golang?sync.Cond同步機(jī)制運(yùn)用及實(shí)現(xiàn)
在?Go?里有專門(mén)為同步通信而生的?channel,所以較少看到?sync.Cond?的使用,不過(guò)它也是并發(fā)控制手段里的一種,今天我們就來(lái)認(rèn)識(shí)下它的相關(guān)實(shí)現(xiàn),加深對(duì)同步機(jī)制的運(yùn)用2023-09-09利用go-zero在Go中快速實(shí)現(xiàn)JWT認(rèn)證的步驟詳解
這篇文章主要介紹了如何利用go-zero在Go中快速實(shí)現(xiàn)JWT認(rèn)證,本文分步驟通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-10-10深入探索Go語(yǔ)言中的高效數(shù)據(jù)結(jié)構(gòu)堆
堆,作為一種基本的數(shù)據(jù)結(jié)構(gòu),以其在優(yōu)先隊(duì)列和排序算法中提供高效解決方案的能力而聞名。在本文中,我們將深入探討堆的內(nèi)部工作原理,包括其特性、實(shí)現(xiàn)細(xì)節(jié)以及在現(xiàn)代編程中的應(yīng)用2008-06-06