您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“golang中nil怎么用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“golang中nil怎么用”這篇文章吧。
golang中的nil
,很多人都誤以為與Java、PHP等編程語言中的null一樣。但是實際上Golang的niu復雜得多了,如果不信,那我們繼續往下閱讀。
nil
為預聲明的標示符,定義在builtin/builtin.go
,
// nil is a predeclared identifier representing the zero value for a// pointer, channel, func, interface, map, or slice type.// Type must be a pointer, channel, func, interface, map, or slice typevar nil Type // Type is here for the purposes of documentation only. It is a stand-in// for any Go type, but represents the same type for any given function// invocation.type Type int
按照Go語言規范,任何類型在未初始化時都對應一個零值:布爾類型是false,整型是0,字符串是"",而指針、函數、interface、slice、channel和map的零值都是nil。
PS:這里沒有說結構體struct的零值為nil,因為struct的零值與其屬性有關
nil
沒有默認的類型,盡管它是多個類型的零值,必須顯式或隱式指定每個nil用法的明確類型。
package main func main() { // 明確. _ = (*struct{})(nil) _ = []int(nil) _ = map[int]bool(nil) _ = chan string(nil) _ = (func())(nil) _ = interface{}(nil) // 隱式. var _ *struct{} = nil var _ []int = nil var _ map[int]bool = nil var _ chan string = nil var _ func() = nil var _ interface{} = nil }
如果關注過golang關鍵字的同學就會發現,里面并沒有nil
,也就是說nil
并不是關鍵字,那么就可以在代碼中定義nil
,那么nil
就會被隱藏。
package mainimport "fmt"func main() { nil := 123 fmt.Println(nil) // 123 var _ map[string]int = nil //cannot use nil (type int) as type map[string]int in assignment }
nil
類型的所有值的內存布局始終相同,換一句話說就是:不同類型nil
的內存地址是一樣的。
package main import ( "fmt" ) func main() { var m map[int]string var ptr *int var sl []int fmt.Printf("%p\n", m) //0x0 fmt.Printf("%p\n", ptr ) //0x0 fmt.Printf("%p\n", sl ) //0x0 }
業務中一般將nil
值表示為異常。nil值的大小始終與其類型與nil
值相同的non-nil
值大小相同。因此, 表示不同零值的nil標識符可能具有不同的大小。
package main import ( "fmt" "unsafe" ) func main() { var p *struct{} = nil fmt.Println( unsafe.Sizeof( p ) ) // 8 var s []int = nil fmt.Println( unsafe.Sizeof( s ) ) // 24 var m map[int]bool = nil fmt.Println( unsafe.Sizeof( m ) ) // 8 var c chan string = nil fmt.Println( unsafe.Sizeof( c ) ) // 8 var f func() = nil fmt.Println( unsafe.Sizeof( f ) ) // 8 var i interface{} = nil fmt.Println( unsafe.Sizeof( i ) ) // 16 }
大小是編譯器和體系結構所依賴的。以上打印結果為64位體系結構和正式 Go 編譯器。對于32位體系結構, 打印的大小將是一半。
對于正式 Go 編譯器, 同一種類的不同類型的兩個nil值的大小始終相同。例如, 兩個不同的切片類型 ( []int和[]string) 的兩個nil值始終相同。
1.不同類型的nil
是不能比較的。
package main import ( "fmt" ) func main() { var m map[int]string var ptr *int fmt.Printf(m == ptr) //invalid operation: m == ptr (mismatched types map[int]string and *int) }
在 Go 中, 兩個不同可比較類型的兩個值只能在一個值可以隱式轉換為另一種類型的情況下進行比較。具體來說, 有兩個案例兩個不同的值可以比較:
兩個值之一的類型是另一個的基礎類型。
兩個值之一的類型實現了另一個值的類型 (必須是接口類型)。
nil
值比較并沒有脫離上述規則。
package main import ( "fmt" ) func main() { type IntPtr *int fmt.Println(IntPtr(nil) == (*int)(nil)) //true fmt.Println((interface{})(nil) == (*int)(nil)) //false }
2.同一類型的兩個nil
值可能無法比較 因為golang中存在map、slice和函數類型是不可比較類型,它們有一個別稱為不可比擬的類型
,所以比較它們的nil
亦是非法的。
package main import ( "fmt" ) func main() { var v1 []int = nil var v2 []int = nil fmt.Println(v1 == v2) fmt.Println((map[string]int)(nil) == (map[string]int)(nil)) fmt.Println((func())(nil) == (func())(nil)) }
不可比擬的類型
的值缺是可以與“純nil”進行比較。
package main import ( "fmt" ) func main() { fmt.Println((map[string]int)(nil) == nil) //true fmt.Println((func())(nil) == nil) //true }
3.兩nil
值可能不相等
如果兩個比較的nil值之一是一個接口值, 而另一個不是, 假設它們是可比較的, 則比較結果總是 false。原因是在進行比較之前, 接口值將轉換為接口值的類型。轉換后的接口值具有具體的動態類型, 但其他接口值沒有。這就是為什么比較結果總是錯誤的。
package main import ( "fmt" ) func main() { fmt.Println( (interface{})(nil) == (*int)(nil) ) // false }
1.函數返回
func nilReturn() (string,error) { return nil,nil //cannot use nil as type string in return argument }
因為error
是接口類型所以error
類型沒有報錯。
2.map的nil key map的key為指針、函數、interface、slice、channel和map,則key可以為nil。
package main import ( "fmt" ) func main() { mmap := make(map[*string]int,4) a:="a" mmap[&a] = 1 mmap[nil] = 99 fmt.Println(mmap) //map[0xc042008220:1 <nil>:99] }
以上是“golang中nil怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。