這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
golang 中的 nil 是不同於其他語言的,為了更好的理解 nil,在此我將嘗試一步一步揭示 nil 在 golang 中的一些操作和現象。
1. nil 是不能比較的
code-1 Play
123456789 |
package mainimport ( "fmt")func main() { fmt.Println(nil==nil)} |
code-1 輸出
1 |
tmp/sandbox318449491/main.go:8: invalid operation: nil == nil (operator == not defined on nil) |
這點和 python 等動態語言是不同的,在 python 中,兩個 None 值永遠相等。
123 |
>>> None == NoneTrue>>> |
從 go 的輸出結果不難看出,== 對於 nil 來說是一種未定義的操作。
2. 預設 nil 是 typed 的
code-2 Play
12345678910 |
package mainimport ("fmt")func main() {fmt.Printf("%T", nil) print(nil)} |
code-2 輸出
1 |
tmp/sandbox379579345/main.go:9: use of untyped nil |
print 的輸出時未指定類型的,因而無法輸出
3. 不同類型 nil 的 address 是一樣的
code-3 Play
123456789101112 |
package mainimport ("fmt")func main() {var m map[int]stringvar ptr *intfmt.Printf("%p", m)fmt.Printf("%p", ptr)} |
m 和 ptr 的 address 都是 0x0
4. 不同類型的 nil 是不能比較的
code-4 Play
1234567891011 |
package mainimport ("fmt")func main() {var m map[int]stringvar ptr *intfmt.Printf(m == ptr)} |
code-4 輸出
1 |
tmp/sandbox618627491/main.go:10: invalid operation: m == ptr (mismatched types map[int]string and *int) |
5. nil 是 map,slice,pointer,channel,func,interface 的零值
code-5 Play
1234567891011121314151617181920 |
package mainimport ("fmt")func main() {var m map[int]stringvar ptr *intvar c chan intvar sl []intvar f func()var i interface{}fmt.Printf("%#v\n", m)fmt.Printf("%#v\n", ptr)fmt.Printf("%#v\n", c)fmt.Printf("%#v\n", sl)fmt.Printf("%#v\n", f)fmt.Printf("%#v\n", i)} |
code-5 輸出
123456 |
map[int]string(nil)(*int)(nil)(chan int)(nil)[]int(nil)(func())(nil)<nil> |
zero value 是 go 中變數在聲明之後但是未初始化被賦予的該類型的一個預設值。
正確理解 nil 是正確理解 go 中類型的重要一環,因而 nil 的任何細節在遇到之後都不要錯過,要做到相應的記錄。