初始化空切片的正确方法

Correct way to initialize empty slice

声明一个空切片,大小不固定, 这样做更好吗:

mySlice1 := make([]int, 0)

或:

mySlice2 := []int{}

只是想知道哪一个是正确的方法。

它们是等价的。请参阅此代码:

mySlice1 := make([]int, 0)
mySlice2 := []int{}
fmt.Println("mySlice1", cap(mySlice1))
fmt.Println("mySlice2", cap(mySlice2))

输出:

mySlice1 0
mySlice2 0

两个切片都有 0 容量,这意味着两个切片都有 0 长度(不能大于容量),这意味着两个切片都没有元素。这意味着 2 个切片在各个方面都是相同的。

查看类似问题:

What is the point of having nil slice and empty slice in golang?

你给出的两个选项在语义上是相同的,但是使用 make([]int, 0) 将导致内部调用 runtime.makeslice (Go 1.16)。

您还可以选择保留 nil 值:

var myslice []int

Golang.org blog中所写:

a nil slice is functionally equivalent to a zero-length slice, even though it points to nothing. It has length zero and can be appended to, with allocation.

然而,

A nil 切片将 json.Marshal() 转换为 "null",而空切片将编组为 "[]",正如@farwayer 所指出的。

正如@ArmanOrdookhani 所指出的,上述选项的

None 将导致任何分配。

Empty slice 和 nil slice 在 Go 中的初始化方式不同:

var nilSlice []int 
emptySlice1 := make([]int, 0)
emptySlice2 := []int{}

fmt.Println(nilSlice == nil)    // true
fmt.Println(emptySlice1 == nil) // false
fmt.Println(emptySlice2 == nil) // false

对于三个切片,len和cap都是0。

作为 @ANisus' 答案的补充...

下面是"Go in action"书中的一些资料,我觉得值得一提:

nilempty 切片之间的差异

如果我们想到这样的切片:

[pointer] [length] [capacity]

然后:

nil slice:   [nil][0][0]
empty slice: [addr][0][0] // points to an address

nil slice

They’re useful when you want to represent a slice that doesn’t exist, such as when an exception occurs in a function that returns a slice.

// Create a nil slice of integers.
var slice []int

empty slice

Empty slices are useful when you want to represent an empty collection, such as when a database query returns zero results.

// Use make to create an empty slice of integers.
slice := make([]int, 0)

// Use a slice literal to create an empty slice of integers.
slice := []int{}

Regardless of whether you’re using a nil slice or an empty slice, the built-in functions append, len, and cap work the same.


Go playground example:

package main

import (
    "fmt"
)

func main() {

    var nil_slice []int
    var empty_slice = []int{}

    fmt.Println(nil_slice == nil, len(nil_slice), cap(nil_slice))
    fmt.Println(empty_slice == nil, len(empty_slice), cap(empty_slice))

}

打印:

true 0 0
false 0 0

除了@ANisus 的回答

使用官方 Go MongoDb Driver 时,nil 切片也将编组到 "null" 而空切片将编组到 "[]".

使用社区支持的 MGO driver 时,nil 和空切片都将编组到 "[]"

参考:https://jira.mongodb.org/browse/GODRIVER-971