詳解Go語言各種常見類型的默認(rèn)值和判空方法
起因(解決的問題)
由于在項(xiàng)目中設(shè)計(jì)到了類型的判空,所以突然好奇起來,每個(gè)類型如果只是聲明,而沒有初始化,那么默認(rèn)值是多少?怎么判斷它是不是空值?所以去整理了一下
基本類型的默認(rèn)值
1.常見的基本數(shù)據(jù)類型有:數(shù)據(jù)類型(int,uint,float之類的),字符串(string),結(jié)構(gòu)體,數(shù)組,指針。
2.那么他們的默認(rèn)值是:
數(shù)據(jù)類型 | 默認(rèn)值 |
int | 0 |
float | 0.00000 |
string | “” |
結(jié)構(gòu)體 | 根據(jù)結(jié)構(gòu)體內(nèi)部的基礎(chǔ)數(shù)據(jù)類型進(jìn)行初始化賦值,下面會(huì)有demo |
數(shù)組(切片) | 空數(shù)組 |
指針 | nil |
3.例子:
package main import ( "fmt" ) type UserInfo struct { Name string Age int Sex string Flag bool } // main函數(shù) func main() { PrintDefault() } // 輸出默認(rèn)值的函數(shù) func PrintDefault() { var a int var b bool var c float64 var d byte var e string var f UserInfo var g *UserInfo var ip *int var bp *bool var fp *float64 var sp *string var ssp *byte var iArray []int fmt.Println("-------默認(rèn)值列表--------") fmt.Printf("int的默認(rèn)值為:%d\n", a) fmt.Printf("bool的默認(rèn)值為:%t\n", b) fmt.Printf("float64的默認(rèn)值為:%f\n", c) fmt.Printf("byte的默認(rèn)值為:%b\n", d) fmt.Printf("string的默認(rèn)值為:%s\n", e) fmt.Printf("結(jié)構(gòu)體UserInfo的默認(rèn)值為:%v\n", f) fmt.Printf("結(jié)構(gòu)體指針UserInfo的默認(rèn)值為:%v\n", g) fmt.Printf("int數(shù)組的默認(rèn)值為:%v\n", iArray) fmt.Printf("int指針的默認(rèn)值為:%p\n", ip) fmt.Printf("byte指針的默認(rèn)值為:%p\n", bp) fmt.Printf("string指針的默認(rèn)值為:%p\n", fp) fmt.Printf("float64指針的默認(rèn)值為:%p\n", sp) fmt.Printf("byte指針的默認(rèn)值為:%p\n", ssp) if ip != nil { fmt.Printf("string指針的默認(rèn)值為:%d\n", *ip) } }
運(yùn)行結(jié)果截圖:
由上可以知道兩個(gè)點(diǎn):
1.各種數(shù)據(jù)類型怎么輸出,對(duì)應(yīng)的d%,v%,s%是什么。(大家可以看一下,后面自己本地測(cè)試輸出日志也方便)
2.了解各種數(shù)據(jù)的默認(rèn)值,總結(jié)來說就是:數(shù)據(jù)類型是0,字符是空字符“”,結(jié)構(gòu)體指針是nil,基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)指針是0x0。
值得注意的是:雖然基礎(chǔ)數(shù)據(jù)類型指針的輸出和結(jié)構(gòu)體指針的輸出不太一樣,但是實(shí)際判空的時(shí)候,都是視為nil的。例如:
var ip *int if ip!=nil{//不會(huì)進(jìn)入該邏輯,即:ip指向了0x0的時(shí)候,是視為nil的 fmt.Printf("string指針的默認(rèn)值為:%d\n", *ip) }
好了,那么了解了各個(gè)數(shù)據(jù)類型的默認(rèn)值,判空就好做多了。
判斷是否初始化(判空)
方法1:
直接判斷它和默認(rèn)值是否一樣,是的話就認(rèn)為是沒有初始化的。(這部分主要是了解原理,實(shí)際我們開發(fā)過程用方法2好點(diǎn))
package main import ( "fmt" "reflect" ) type UserInfo struct { Name string Age int Sex string Flag bool } func main() { fmt.Println("-----------判斷類型函數(shù)實(shí)驗(yàn)----------") var a int var b bool var c float64 var d byte var e string var f UserInfo var g *UserInfo var ip *int var sp *string if g == nil { fmt.Println("nil判斷成功") } var iSlice []int var iArray [2]int CheckType(a) CheckType(b) CheckType(c) CheckType(d) CheckType(e) CheckType(f) CheckType(g) CheckType(ip) CheckType(sp) CheckType(iArray) CheckType(iSlice) } // 自己寫了一個(gè)判空函數(shù),你可以直接看判空部分的邏輯就好了。 func CheckType(args ...interface{}) { for _, arg := range args { fmt.Printf("數(shù)據(jù)類型為:%s\n", reflect.TypeOf(arg).Kind().String()) //先利用反射獲取數(shù)據(jù)類型,再進(jìn)入不同類型的判空邏輯 switch reflect.TypeOf(arg).Kind().String() { case "int": if arg == 0 { fmt.Println("數(shù)據(jù)為int,是空值") } case "string": if arg == "" { fmt.Println("數(shù)據(jù)為string,為空值") } else { fmt.Println("數(shù)據(jù)為string,數(shù)值為:", arg) } case "int64": if arg == 0 { fmt.Println("數(shù)據(jù)為int64,為空值") } case "uint8": if arg == false { fmt.Println("數(shù)據(jù)為bool,為false") } case "float64": if arg == 0.0 { fmt.Println("數(shù)據(jù)為float,為空值") } case "byte": if arg == 0 { fmt.Println("數(shù)據(jù)為byte,為0") } case "ptr": if arg == nil { //接口狀態(tài)下,它不認(rèn)為自己是nil,所以要用反射判空 fmt.Println("數(shù)據(jù)為指針,為nil") } else { fmt.Println("數(shù)據(jù)不為空,為", arg) } //反射判空邏輯 if reflect.ValueOf(arg).IsNil() { //利用反射直接判空 fmt.Println("反射判斷:數(shù)據(jù)為指針,為nil") fmt.Println("nil:", reflect.ValueOf(nil).IsValid()) //利用反射判斷是否是有效值 } case "struct": if arg == nil { fmt.Println("數(shù)據(jù)為struct,為空值") } else { fmt.Println("數(shù)據(jù)為struct,默認(rèn)有數(shù),無法判空,只能判斷對(duì)應(yīng)指針有沒有初始化,直接結(jié)構(gòu)體無法判斷") } case "slice": s := reflect.ValueOf(arg) if s.Len() == 0 { fmt.Println("數(shù)據(jù)為數(shù)組/切片,為空值") } case "array": s := reflect.ValueOf(arg) if s.Len() == 0 { fmt.Println("數(shù)據(jù)為數(shù)組/切片,為空值") } else { fmt.Println("數(shù)據(jù)為數(shù)組/切片,為", s.Len()) } default: fmt.Println("奇怪的數(shù)據(jù)類型") } } }
運(yùn)行結(jié)果截圖:
由上可知?;具€是那句話:數(shù)據(jù)類型默認(rèn)0,指針類型默認(rèn)nil(接口類型下,空指針==nil會(huì)不通過,要用反射判空),字符類型為空字符串“”。
方式2:
利用反射包的內(nèi)置函數(shù)判空. 正如上面展示的指針判空邏輯。實(shí)際上go已經(jīng)有一個(gè)反射包里面封裝了判斷
package main import ( "fmt" "reflect" ) type UserInfo struct { Name string Age int Sex string Flag bool } func main() { fmt.Println("-----------指針類型判空實(shí)驗(yàn)----------") var g *UserInfo var ip *int var sp *string var iSlice []int CheckTypeByReflectNil(g) CheckTypeByReflectNil(ip) CheckTypeByReflectNil(sp) CheckTypeByReflectNil(iSlice) fmt.Println("-----------基礎(chǔ)類型判空實(shí)驗(yàn)----------") var a int var b bool var c float64 var d byte var e string var f UserInfo CheckTypeByReflectZero(a) CheckTypeByReflectZero(b) CheckTypeByReflectZero(c) CheckTypeByReflectZero(d) CheckTypeByReflectZero(e) CheckTypeByReflectZero(f) } func CheckTypeByReflectNil(arg interface{}) { if reflect.ValueOf(arg).IsNil() { //利用反射直接判空,指針用isNil // 函數(shù)解釋:isNil() bool 判斷值是否為 nil // 如果值類型不是通道(channel)、函數(shù)、接口、map、指針或 切片時(shí)發(fā)生 panic,類似于語言層的v== nil操作 fmt.Printf("反射判斷:數(shù)據(jù)類型為%s,數(shù)據(jù)值為:%v,nil:%v \n", reflect.TypeOf(arg).Kind(), reflect.ValueOf(arg), reflect.ValueOf(arg).IsValid()) } } func CheckTypeByReflectZero(arg interface{}) { if reflect.ValueOf(arg).IsZero() { //利用反射直接判空,基礎(chǔ)數(shù)據(jù)類型用isZero fmt.Printf("反射判斷:數(shù)據(jù)類型為%s,數(shù)據(jù)值為:%v,nil:%v \n", reflect.TypeOf(arg).Kind(), reflect.ValueOf(arg), reflect.ValueOf(arg).IsValid()) } }
運(yùn)行結(jié)果截圖:
到此這篇關(guān)于詳解Go語言各種常見類型的默認(rèn)值和判空方法的文章就介紹到這了,更多相關(guān)Go語言常見類型的默認(rèn)值和判空內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang編程并發(fā)工具庫MapReduce使用實(shí)踐
這篇文章主要為大家介紹了Golang并發(fā)工具庫MapReduce的使用實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Go基礎(chǔ)教程系列之?dāng)?shù)據(jù)類型詳細(xì)說明
這篇文章主要介紹了Go基礎(chǔ)教程系列之?dāng)?shù)據(jù)類型詳細(xì)說明,需要的朋友可以參考下2022-04-04使用Golang實(shí)現(xiàn)Sm2加解密的代碼詳解
本文主要介紹了Go語言實(shí)現(xiàn)Sm2加解密的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03