go nil處理如何正確返回nil的error
i == nil 會生效
對于下面這段代碼,我們知道 i 實(shí)際上的值就是 nil,所以 i == nil 會生效
func main() {
var i *int = nil
if i == nil {
fmt.Println("i is nil") // i is nil
}
}現(xiàn)在換一種寫法,我們將 i 的類型改成 interface{},i == nil 依然會生效
func main() {
var i interface{} = nil
if i == nil {
fmt.Println("i is nil") // i is nil
}
}我們接著改造,將 i == nil 的邏輯封裝成函數(shù) IsNil
func IsNil(i interface{}) {
if i == nil {
fmt.Println("i is nil")
}
}
func main() {
var i *int = nil
IsNil(i)
}IsNil 中的 i == nil 不生效
然后居然發(fā)現(xiàn) IsNil 中的 i == nil 不生效了,為什么呢?
因?yàn)閷τ?nbsp;interface{} 類型的值來說,如果要判斷它是 nil,必須同時(shí)滿足 type T 和 value V 都是 nil 才行
可以用 reflect 中的 TypeOf 和 ValueOf
var i *int = nil
fmt.Println(reflect.TypeOf(i), reflect.ValueOf(i)) // *int <nil>
var i interface{} = nil
fmt.Println(reflect.TypeOf(i), reflect.ValueOf(i)) // <nil> <invalid reflect.Value>但是如果我們在函數(shù)中用 interface{} 作為參數(shù)的類型,表示并不代表參數(shù)就是 interface{} 類型,而是任意類型,調(diào)用時(shí)傳入啥類型就是啥類型,如下代碼
var i interface{} = 1
fmt.Println(reflect.TypeOf(i)) // int
var j interface{} = "hello"
fmt.Println(reflect.TypeOf(j)) // string
var k interface{} = nil
fmt.Println(reflect.TypeOf(k)) // nil所以只有當(dāng)我們傳入類型的參數(shù)是 interface{} 類型時(shí),且 value 為 nil 時(shí),i == nil 才會生效
否則其他情況都不會生效
func main() {
var i interface{} = nil
IsNil(i) // i is nil
}
func IsNil(i interface{}) {
if i == nil {
fmt.Println("i is nil")
}
}這個(gè)坑可能會出現(xiàn)在返回 error 的函數(shù)中,比如下面這段代碼
在函數(shù) SomeThing 中提前定義了 myError,然后一系列的處理后,返回了 myError
業(yè)務(wù)邏輯
后面的業(yè)務(wù)邏輯需要判斷 err 是否為 nil
type MyError struct{}
func (me *MyError) Error() string {
return "my error"
}
func SomeThing() error {
var myError *MyError // 默認(rèn)初始化為 nil
// ...
return myError
}
func main() {
err := SomeThing()
fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err)) // *main.MyError <nil>
if err != nil { // 雖然沒有返回,這里會被執(zhí)行,因?yàn)?err 的類型不是 nil
fmt.Println(err)
}
}從上面的代碼我們看到,SomeThing 函數(shù)中定義的 myError 是 *MyError 類型,雖然返回了 nil,但是 err 的類型不是 nil,所以 err != nil 會生效,不符合預(yù)期
如果修改這個(gè)問題呢,當(dāng)我們需要返回 nil 時(shí),顯示指明返回 nil,如下代碼:
type MyError struct{}
func (me *MyError) Error() string {
return "my error"
}
func SomeThing() error {
var myError *MyError // 默認(rèn)初始化為 nil
// ...
return nil
}
func main() {
err := SomeThing()
fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err)) // <nil> <invalid reflect.Value>
if err != nil { // 這段代碼不會被執(zhí)行
fmt.Println(err)
}
}總結(jié)
需要返回 nil 時(shí),要顯示返回 nil,不要用指針類型的零值
以上就是go nil處理如何正確返回nil的error的詳細(xì)內(nèi)容,更多關(guān)于go nil處理返回error的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go gin權(quán)限驗(yàn)證實(shí)現(xiàn)過程詳解
這篇文章主要為大家介紹了Go gin權(quán)限驗(yàn)證實(shí)現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Golang中crypto/cipher加密標(biāo)準(zhǔn)庫全面指南
本文主要介紹了Golang中crypto/cipher加密標(biāo)準(zhǔn)庫,包括對稱加密、非對稱加密以及使用流加密和塊加密算法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02
Go語言通過TCP協(xié)議實(shí)現(xiàn)聊天室功能
這篇文章主要為大家詳細(xì)介紹了Go語言中如何通過TCP協(xié)議實(shí)現(xiàn)聊天室功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
Go語言通過chan進(jìn)行數(shù)據(jù)傳遞的方法詳解
這篇文章主要為大家詳細(xì)介紹了Go語言如何通過chan進(jìn)行數(shù)據(jù)傳遞的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-06-06
goland把go項(xiàng)目打包進(jìn)docker鏡像的全過程記錄
golang編譯的應(yīng)用是不需要依賴其他運(yùn)行環(huán)境的,下面這篇文章主要給大家介紹了關(guān)于goland把go項(xiàng)目打包進(jìn)docker鏡像的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
Golang 空map和未初始化map的注意事項(xiàng)說明
這篇文章主要介紹了Golang 空map和未初始化map的注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04

