初始化空切片的正确方法

Correct way to initialize empty slice

提问人:eouti 提问时间:3/20/2015 最后编辑:eouti 更新时间:6/24/2021 访问量:482195

问:

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

mySlice1 := make([]int, 0)

艺术

mySlice2 := []int{}

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

数组 切片

评论

3赞 Dave C 3/21/2015
你说“非固定大小”,但切片从来没有固定大小。除非你的意思是零容量。请注意,如果您对可能需要的容量有想法/猜测/提示,那么使用三个参数版本是好的。例如,构建一个地图键切片:keys := make([]int, 0, len(m)); for k, v := range m { keys := append(keys,k) }
1赞 user 11/21/2015
声明切片或制作切片的可能副本?

答:

130赞 icza 3/20/2015 #1

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

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

输出:

mySlice1 0
mySlice2 0

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

查看类似问题:

在 golang 中拥有 nil slice 和 empty slice 有什么意义?

Go 语言中的 nil 切片 vs 非 nil 切片 vs 空切片

461赞 ANisus 3/20/2015 #2

您给出的两个替代方案在语义上是相同的,但使用将导致对 runtime.makeslice (Go 1.16) 的内部调用。make([]int, 0)

您还可以选择将其保留为一个值:nil

var myslice []int

正如 Golang.org 博客中所写:

零切片在功能上等同于零长度切片,即使它不指向任何内容。它的长度为零,可以附加到分配中。

然而,一个切片将进入,而一个空切片将编组成,正如@farwayer所指出的。niljson.Marshal()"null""[]"

正如@ArmanOrdookhani所指出的,上述选项都不会造成任何分配。

评论

4赞 Grzegorz Żur 3/20/2015
还在 wiki github.com/golang/go/wiki/ 上提及...
170赞 farwayer 7/12/2017
注意:将返回初始化切片和初始化切片json.Marshal()nullvar myslice []int[]myslice := []int{}
15赞 asgaines 6/13/2018
还要注意:区分无切片和非无切片:, ,reflect.DeepEquala := []int{}var b []intreflect.DeepEqual(a, b) // returns false
1赞 Arman Ordookhani 4/21/2020
你为什么认为它会进行分配?上限为零,因此不分配任何内容。指向零长度事物的所有指针都指向内存中的同一位置:play.golang.org/p/MPOKKl_sYvw
2赞 ANisus 4/29/2021
@КонстантинВан 从 Go 1.16 开始,它们不会生成相同的代码,正如你在这里看到的。使用 make 调用 runtime.makeslice,即使对于长度为零的切片,而空切片文本直接使用 runtime.zerobase这意味着,Go 1.16 中的文字速度略快。
18赞 Joe.CK 3/21/2017 #3

空切片和零切片在 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。

评论

1赞 Andrzej Rehmann 12/26/2018
make([]int, 0)是最好的,因为 Jetbrains GoLand 不会像 .这在编写单元测试时很有用。[]int{}
66赞 tgogos 9/1/2017 #4

作为@ANisus回答的补充......

以下是《Go in action》一书中的一些信息,我认为值得一提:

& 切片之间的区别nilempty

如果我们考虑这样的切片:

[pointer] [length] [capacity]

然后:

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

无切片

当您想要表示不存在的切片时,例如,当返回切片的函数中发生异常时,它们非常有用。

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

空切片

当您想要表示空集合时(例如,当数据库查询返回零个结果时),空切片非常有用。

// 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{}

无论您使用的是 nil 切片还是空切片,内置函数 、 和 的工作方式都是一样的。appendlencap


Go playground 示例

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

评论

0赞 Cloud 7/16/2018
我们可以使用一步到位得到空切片的地址吗?make
0赞 tgogos 7/16/2018
如果我们看一下函数签名,似乎没有返回地址。我相信你不能一步到位。make
2赞 Tsvetelin Pantev 6/22/2021 #5

除了@ANisus的回答

使用官方的 Go MongoDb 驱动程序时,切片也会编组成,而空切片将编组成 .nil"null""[]"

使用社区支持的 MGO 驱动程序时,空切片和空切片都将封组到 .nil"[]"

编号: https://jira.mongodb.org/browse/GODRIVER-971