在 Go 語言中,有一種稱為 slice 的型別,它是建立在 array 之上的。當我們想要處理一組資料時,它是一種非常方便的型別。這篇文章將解釋 empty slice 和 nil slice 之間一個微妙但棘手的差異。
nil slice 是一個長度和容量均為零且沒有底層陣列的 slice。 slice 的零值為 nil。如果像下面這樣宣告一個 slice,它就是一個 nil slice。
package main
import "fmt"
func main() {
var a []string
fmt.Println(a == nil)
}
對於上面的程式碼片段,輸出將為 true 。
empty slice 也是一個長度和容量均為零的 slice,但具有長度為零的底層陣列。如果像下面這樣宣告一個 slice,它就是一個 empty slice。
package main
import "fmt"
func main() {
b := []string{}
fmt.Println(b == nil)
}
對於上面的程式碼片段,輸出將為 false 。
也可以使用 make() 函數建立一個 empty slice。
package main
import "fmt"
func main() {
c := make([]string, 0)
fmt.Println(c == nil)
}
在大多數情況下,empty slice 和 nil slice 可以被視為相同。僅在某些微妙的情況下,它們應被區別對待,其中一種情況是在進行 JSON 編碼時。
empty slice 將在 JSON 中編碼為 [],而 nil slice 將編碼為 null。
package main
import (
"fmt"
"encoding/json"
)
type A struct {
Data []string
}
func main() {
var a []string
fmt.Println(a == nil)
as := &A{
Data: a,
}
aj, _ := json.Marshal(as)
fmt.Printf("%s\n", string(aj))
b := []string{}
fmt.Println(b == nil)
bs := &A{
Data: b,
}
bj, _ := json.Marshal(bs)
fmt.Printf("%s\n", string(bj))
}
// true
// {"Data":null}
// false
// {"Data":[]}
當此值作為 API 回應返回時,這將產生很大的差異。前端需要以非常不同的方式對待它。通常,nil slice 是一種首選樣式。