【问题标题】:Declare slice or make slice?声明切片还是制作切片?
【发布时间】:2014-10-22 00:06:00
【问题描述】:

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

我发现两者都有效,但哪个更好?

【问题讨论】:

  • 第一个创建nil 切片,而第二个创建empty 切片(这是“Go in action book” 使用的术语)。为避免在此处也发布相同的答案,您可以查看stackoverflow.com/a/45997533/1561148

标签: go allocation slice


【解决方案1】:

简单的声明

var s []int

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

s := make([]int, 0)

分配内存,s 指向内存为 0 个元素的切片。

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

【讨论】:

  • 我可以对地图说同样的话吗? var m map[string]int vs m:= make(map[string]int) ?谢谢。
  • 不,您需要make 映射,因为即使是空的map 也需要分配空间用于记账。
  • 如果你需要返回一个包含 0 个元素的切片(而不是 'nil'),make 是正确的用法。
  • 如果你正在构建一个 API 并返回一个数组作为响应,使用声明形式将返回 nil 以防你的切片没有任何元素,而不是一个空数组。但是,如果使用make创建切片,则会返回一个空数组,这通常是想要的效果。
  • 正如对此答案的评论中提到的:stackoverflow.com/a/29164565/1311538,在尝试执行 json 封送处理等操作时存在差异。编组 nil 切片 (var s []int) 将产生 null,而编组空切片 (s := make([]int, 0)) 将产生预期的 []
【解决方案2】:

除了fabriziomanswer,您还可以在“Go Slices: usage and internals”看到更多示例,其中提到了[]int 的用法:

由于切片的零值 (nil) 的作用类似于零长度切片,因此您可以声明切片变量,然后在循环中附加到它:

// 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,都不会分配任何内容。
  • @ArmanOrdookhani 同意。我只是发现声明 var p []int 比使用 make 更容易(我更多地将其与分配相关联,即使上限为 0,它也不会分配任何东西)。在可读性方面,我不喜欢在这里使用make
  • 我更倾向于在任何地方使用文字(例如p := []int{})。由于我们通常使用:= 语法来声明大多数变量,因此在任何地方都有它而不是切片异常更自然。除此之外,试图考虑分配通常会将人们推向过早的优化。
【解决方案3】:

刚刚发现不同之处。如果你使用

var list []MyObjects

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

list := make([]MyObjects, 0)

结果如预期的那样[]

【讨论】:

  • 是的,当我们想用 [] 数组而不是 null 来响应时,后者非常有用
【解决方案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>]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2016-07-22
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    相关资源
    最近更新 更多