nil 空值
什麼? nil 是一種資料型態? 還是 nil 值? 你在跟我開玩笑嗎?
不只是 golang ... 在每個語言中 nil 都是非常重要的,它代表的是空。
而 ... 在不同語言中,「空」的概念都有些細微的不同。
比方說 ...
在 scheme 中,nil 是 true 的!
在 C 中 NULL 跟 0 是等價的。
昨天說到 golang 的任何變數型態在宣告時,都對應到一個初值
false for booleans
0 for numeric
"" for strings
nil for pointers, functions, interfaces, slices, channels, and maps
golang 中的 nil 是不同於其他語言的,為了理解 nil,我們來一點一點、慢慢地揭開 nil 神秘的面紗
nil 是不能被比較的,沒有這種東西:
if nil == nil
nil 可以出現在 if 的右邊,常用於錯誤判斷
if err != nil {
log.println(err)
return
}
不同資料型態的 nil 的 address 是一樣的
var m map[int]string
var ptr *int
fmt.Printf("%p", m)
fmt.Println("")
fmt.Printf("%p", ptr)
輸出為
0x0
0x0
m 是一個 map,ptr 是一個 pointer
但 ... m 和 ptr 的 address 都是 0x0
nil 是 map,slice,pointer,channel,func,interface 的初值
var m map[int]string
var ptr *int
var c chan int
var sl []int
var 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)
輸出為
map[int]string(nil)
(*int)(nil)
(chan int)(nil)
[]int(nil)
(func())(nil)
注意:struct 的初值不是 nil,而是該 struct 旗下,每個變數自己的初值。且不能將 struct 類型和 nil 進行比較,會跳紅字,無法編譯
nil 不是 golang 的關鍵字
而且 ... nil 的值可以被更改(下面是個不好的示範
nil := 123
fmt.Println(nil) // 123
// The following line fails to compile,
// for nil represents an int value now
// in this scope.
var _ map[string]int = nil
純屬娛樂,請勿這樣使用,如果造成其他不可預期的後遺症 ...
請不要來找我(X
PS: null 以及 NULL 在許多其他語言也不是關鍵字
不同資料型態的 nil 值的大小可能會有所不同
同型態變數所佔的記憶體都是相同的,nil 值佔記憶體的大小始終與類型與 nil 值相同的非 nil 值的大小相同。
but ...,不同變數型態的 nil 的記憶體可能具有不同的大小。
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
對 golang 來說,相同變數型態的兩個值的大小 nil 始終相同。
ex:所有不同的 slice 來說,當 slice 為空時,其 nil 值的大小都相同。
nil 是 golang 中一個熟悉而重要的 default 值。它是很多資料型態 零值(zero values)的表示方式。 很多有一些其他語言轉 go 的開發人員視 nil 為他語言 null (或者 NULL) 的複製品
恩 ... 有部分是正確的,但是 Go 中的 nil 和其他語言的 null(或者 NULL)有很多不同之處。
ex : 我們可以直接使用 nil 而不用宣告他。
理解 nil 是學習 golang 一個很重要的部分。
nil 之所以比較難以理解,是因為我們經常搞混 nil value 和 nil type 的區別,value vs type 當然是不一樣的哦 >.^
從上面 nil slice和 empty slice 的不同 延伸,其實 empty slice 也可以作為 slice 的 zero value。特地發明一個 nil 值,應該是 golang 出於對性能的考虑。
nil pointer 其實是一切 nil 值的根本型態,可以使用的部分就這麼多
能省下的記憶體就先省下來,pointer 就先讓他 nil 著。
if err != nil {
panic(err)
}
Go 有自己特殊的錯誤處理方式(例如 Java 使用 try..catch),正因為錯誤發生時,是傳回錯誤,所以有許多方式可以檢查錯誤
nils in Go