Go中零值與空值的實現(xiàn)與區(qū)別
內(nèi)置類型的零值/默認值
變量聲明但未顯式初始化時,Go 自動賦的默認值。它保證“未初始化”也有確定、可用的值
| TYPE | ZERO VALUE |
|---|---|
| Integer | 0 |
| Floating point | 0.0 |
| Boolean | false |
| String | "" |
| Pointer | nil |
| Interface | nil |
| Slice | nil |
| Map | nil |
| Array | fields zero (每個元素都是其零值) |
| Struct | fields zero (每個元素都是其零值) |
| Channel | nil |
| Function | nil |
Json序列化中的omitempty&omitzero
omitempty
當(dāng)對一個結(jié)構(gòu)體的某個字段的tag設(shè)置為omitempty時,如果這個字段是空值(empty value,和零值不一樣)時,那么這個字段就會在序列化時省略
The “omitempty” option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.
omitempty標簽的判斷邏輯如下:
- 對于布爾類型:
false被視為空 - 對于數(shù)值類型:
0被視為空 - 對于指針、接口:
nil被視為空 - 對于字符串:
""(空字符串)被視為空 - 對于數(shù)組、切片、map:長度為0被視為空,既包含未初始化的又包含空的
對于空結(jié)構(gòu)體、所有字段都為默認值的零值結(jié)構(gòu)體、以及一些實際含義為零的結(jié)構(gòu)體(例如time.Time{}),omitempty都無能為力,會進行輸出。
因此在Go 1.24之前想對某個結(jié)構(gòu)體不輸出,可選的一種方案是使用指針類型
type VanillaStruct struct {
StructTyp1 struct{} // 空結(jié)構(gòu)體
StructTyp2 struct{ A int } // 零值結(jié)構(gòu)體
TimeTyp time.Time // 實際含義為零的結(jié)構(gòu)體
?
StructTyp3 *struct{}
StructTyp4 *struct{ A int }
TimeTyp2 *time.Time
}
?
type OmitemptyStruct struct {
StructTyp1 struct{} `json:",omitempty"`
StructTyp2 struct{ A int } `json:",omitempty"`
TimeTyp1 time.Time `json:",omitempty"`
?
StructTyp3 *struct{} `json:",omitempty"`
StructTyp4 *struct{ A int } `json:",omitempty"`
TimeTyp2 *time.Time `json:",omitempty"`
}
?
func main() {
s1 := VanillaStruct{}
ss1, err := json.Marshal(s1)
fmt.Println(err, string(ss1))
// {"StructTyp1":{},"StructTyp2":{"A":0},"TimeTyp":"0001-01-01T00:00:00Z","StructTyp3":null,"StructTyp4":null,"TimeTyp2":null}
?
s2 := OmitemptyStruct{}
ss2, err := json.Marshal(s2)
fmt.Println(err, string(ss2))
// {"StructTyp1":{},"StructTyp2":{"A":0},"TimeTyp1":"0001-01-01T00:00:00Z"}
}
omitzero
Go 1.24 給 encoding/json 新增omitzero:按零值(zero value)省略
在序列化時,omitzero選項指定如果字段值為零,則該結(jié)構(gòu)體字段應(yīng)被省略
- 如果該類型定義了
IsZero() bool方法,那么這個零值就通過IsZero方法來判斷 - 否則是根據(jù)字段是否是零值(通過
reflect.Value.IsZero判斷)來判斷
type VanillaStruct struct {
StructTyp1 struct{} // 空結(jié)構(gòu)體
StructTyp2 struct{ A int } // 零值結(jié)構(gòu)體
TimeTyp time.Time // 實際含義為零的結(jié)構(gòu)體
}
?
type OmitzeroStruct struct {
StructTyp1 struct{} `json:",omitzero"`
StructTyp2 struct{ A int } `json:",omitzero"`
TimeTyp1 time.Time `json:",omitzero"`
}
?
func main() {
s1 := VanillaStruct{}
ss1, err := json.Marshal(s1)
fmt.Println(err, string(ss1))
// {"StructTyp1":{},"StructTyp2":{"A":0},"TimeTyp":"0001-01-01T00:00:00Z"}
?
s2 := OmitzeroStruct{}
ss2, err := json.Marshal(s2)
fmt.Println(err, string(ss2))
// {}
}
總結(jié)
下面是一個完整的Go示例,展示了omitempty&omitzero標簽在不同類型上的應(yīng)用:
| TYPE | ZERO VALUE | EMPTY VALUE | WITHOUT OMIT | OMITEZERO | OMITEMPTY |
|---|---|---|---|---|---|
| Integer | 0 | 0 | 0 | OMIT | OMIT |
| Floating point | 0 | 0 | 0 | OMIT | OMIT |
| Boolean | FALSE | FALSE | FALSE | OMIT | OMIT |
| String | "" | "" | "" | OMIT | OMIT |
| Pointer | nil | nil | null | OMIT | OMIT |
| Interface | nil | nil | null | OMIT | OMIT |
| Slice | nil | nil | null | OMIT | OMIT |
| Slice | nil | make([]T, 0) | [] | [] | OMIT |
| Map | nil | nil | null | OMIT | OMIT |
| Map | nil | make(map[K]V, 0) | {} | {} | OMIT |
| Array: [0]T | fields zero | [0]T | [] | OMIT | OMIT |
| Array: [N]T | fields zero | ? | [T] | OMIT | [T] |
| Struct: struct{} | fields zero | ? | {} | OMIT | {} |
| Struct: struct{ F T } | fields zero | ? | {"F": T} | OMIT | {"F": T} |
| Channel | nil | nil | ? | ? | ? |
| Function | nil | nil | ? | ? | ? |
到此這篇關(guān)于Go中零值與空值的實現(xiàn)與區(qū)別的文章就介紹到這了,更多相關(guān)Go 零值 空值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解go-zero如何使用validator進行參數(shù)校驗
這篇文章主要介紹了如何使用validator庫做參數(shù)校驗的一些十分實用的使用技巧,包括翻譯校驗錯誤提示信息、自定義提示信息的字段名稱、自定義校驗方法等,感興趣的可以了解下2024-01-01
Go語言使用kafka-go實現(xiàn)Kafka消費消息
本篇文章主要介紹了使用kafka-go庫消費Kafka消息,包含F(xiàn)etchMessage和ReadMessage的區(qū)別和適用場景,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的可以了解一下2024-12-12
Go第三方框架ants協(xié)程池框架的實現(xiàn)
本文主要介紹了Go第三方框架ants協(xié)程池框架的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2026-04-04
golang-gin-mgo高并發(fā)服務(wù)器搭建教程
這篇文章主要介紹了golang-gin-mgo高并發(fā)服務(wù)器搭建教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Golang基于Vault實現(xiàn)敏感數(shù)據(jù)加解密
數(shù)據(jù)加密是主要的數(shù)據(jù)安全防護技術(shù)之一,敏感數(shù)據(jù)應(yīng)該加密存儲在數(shù)據(jù)庫中,降低泄露風(fēng)險,本文將介紹一下利用Vault實現(xiàn)敏感數(shù)據(jù)加解密的方法,需要的可以參考一下2023-07-07

