💡 Go中的空片与零片的对比

193 阅读2分钟

Go中的片断可以由3个元素表示。

  • ptr - 一个指向底层数组的指针,包含了该片的数据
  • len - 长度,分片中的元素数
  • cap - 容量,底层数据数组中的元素数,从""指向的元素开始。ptr

一个声明为var s1 []stringnil slice没有底层数据数组--它没有指向任何东西。一个声明为s2 := []string{}s3 := make([]string, 0) 的空片子指向一个空的、非零的数组。

也请详细了解切片的长度和容量有什么区别

参见表格来比较nil 和空片的属性。

ptr长度cap
nil:[]string000
空。[]string{}<地址00
空的。make([]string, 0)<地址00

<addr> ,是一个非零的地址,指向一个空的、非零的阵列。

package main
import "fmt"
func main() {
var s1 []string // nil
 s2 := []string{} // empty
 s3 := make([]string, 0) // empty, equivalent to s2 := []string{}

fmt.Printf("s1 is nil: %t, len: %d, cap: %d\n", s1 == nil, len(s1), cap(s1))
fmt.Printf("s2 is nil: %t, len: %d, cap: %d\n", s2 == nil, len(s2), cap(s2))
fmt.Printf("s3 is nil: %t, len: %d, cap: %d\n", s3 == nil, len(s3), cap(s3))
}

输出。

s1 is nil: true, len: 0, cap: 0
s2 is nil: false, len: 0, cap: 0
s3 is nil: false, len: 0, cap: 0

空片和nil 片的行为是一样的,就是内置函数如len(),cap(),append(), 和for .. range 循环返回同样的结果。因此,由于nil slice声明更简单,你应该更喜欢它而不是创建一个空slice。然而,在某些情况下,你可能需要空的、非零的片断。例如,当你想返回一个空的JSON数组[] 作为HTTP响应时,你应该创建空的分片([]string{}make([]string, 0) ),因为如果你使用nil 分片,在编码后你会得到一个null JSON数组。

package main
import (
"encoding/json"
"fmt"
"log"
)
func main() {
var s1 []string // nil
 s2 := []string{} // empty
 s3 := make([]string, 0) // empty, equivalent to s2 := []string{}

s1JSON, err := json.Marshal(s1)
if err != nil {
log.Fatal(err)
}
fmt.Printf("s1 JSON: %s\n", string(s1JSON))
s2JSON, err := json.Marshal(s2)
if err != nil {
log.Fatal(err)
}
fmt.Printf("s2 JSON: %s\n", string(s2JSON))
s3JSON, err := json.Marshal(s3)
if err != nil {
log.Fatal(err)
}
fmt.Printf("s3 JSON: %s\n", string(s3JSON))
}

输出。

s1 JSON: null
s2 JSON: []
s3 JSON: []