声明切片还是制作切片?


99

在Go中,var s []int和之间有什么区别s := make([]int, 0)

我发现这两种方法都可行,但是哪一种更好?


第一个创建一个nil切片,而第二个创建一个empty切片(这是“行动指南”中使用的术语)。为了避免在此处也发布相同的答案,您可以检查stackoverflow.com/a/45997533/1561148
tgogos

Answers:


95

除了fabriziom答案外,您还可以在“ 转到切片:用法和内部方法 ”中看到更多示例,其中[]int提到了的用法:

由于slice(nil)的零值就像一个零长度的slice一样,您可以声明一个slice变量,然后在循环中附加到它:

// Filter returns a new slice holding only
// the elements of s that satisfy f()
func Filter(s []int, fn func(int) bool) []int {
    var p []int // == nil
    for _, v := range s {
        if fn(v) {
            p = append(p, v)
        }
    }
    return p
}

这意味着,要附加到切片,您不必先分配内存:nil切片p int[]足以作为要添加的切片。


为什么您认为它将进行分配?上限为零,因此无论有无make,都不会分配任何内容。
Arman Ordookhani

1
@ArmanOrdookhani同意。我只是发现声明var p []int比使用起来容易make(我将其与分配相关联,即使上限为0,也不会分配任何内容)。在可读性方面,我宁愿不在make这里使用。
VonC

1
我更倾向于在各处使用文字(例如p := []int{})。由于我们通常使用:=语法来声明大多数变量,因此将其随处可见而不是对切片有异常是更自然的。除此之外,尝试考虑分配通常会促使人们进行过早的优化。
Arman Ordookhani

113

简单声明

var s []int

不分配内存并s指向nil,而

s := make([]int, 0)

分配内存并将s内存指向具有0个元素的切片。

通常,如果您不知道用例的确切大小,第一个更惯用。


我可以对地图说同样的话吗?var m map [string] int vs m:= make(map [string] int)吗?谢谢。
2015年

11
不,您需要make映射,因为即使是空的也map需要分配一些簿记空间。
twotwotwo

11
如果需要返回包含0个元素的切片(而不是'nil'),则make是正确的用法。
杰西

6
如果您正在构建API并返回一个数组作为响应,则nil在您的slice没有任何元素(而不是空数组)的情况下,将使用声明性形式返回。但是,如果make用于创建切片,则将返回一个空数组,这通常是所需的效果。
robinmitra

6
如对此答案的评论中所述:stackoverflow.com/a/29164565/1311538,尝试执行json封送处理之类的操作时存在差异。封送nil切片(var s []int)将产生null,而封送空切片(s := make([]int, 0))将产生预期的[]
asgaines

8

刚发现有所不同。如果您使用

var list []MyObjects

然后将输出编码为JSON,得到null

list := make([]MyObjects, 0)

结果[]符合预期。


是的,当我们想用[]数组而不是null响应时,后者非常有用
Nhan Tran

4

更加完整的make示例(中有一个参数):

slice := make([]int, 2, 5)
fmt.Printf("length:  %d - capacity %d - content:  %d", len(slice), cap(slice), slice)

出:

length:  2 - capacity 5 - content:  [0 0]

或具有动态类型slice

slice := make([]interface{}, 2, 5)
fmt.Printf("length:  %d - capacity %d - content:  %d", len(slice), cap(slice), slice)

出:

length:  2 - capacity 5 - content:  [<nil> <nil>]

2
很好的例子。+1
VonC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.