正确初始化空切片的方法

eou*_*uti 184 arrays go slice

要声明具有非固定大小的空切片,最好是:

mySlice1 := make([]int, 0)
Run Code Online (Sandbox Code Playgroud)

要么:

mySlice2 := []int{}
Run Code Online (Sandbox Code Playgroud)

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

ANi*_*sus 228

你给出的两个替代方案在语义上是相同的,我会假设他们生成相同的汇编指令.

为避免不必要的分配,如果您最终不使用切片,可以为其保留一个nil值:

var myslice []int
Run Code Online (Sandbox Code Playgroud)

正如Golang.org博客中所写:

nil切片在功能上等同于零长度切片,即使它指向任何东西.它的长度为零,可以通过分配附加到.

  • 小心:`json.Marshal()`将为`var myslice [] int`和`[]`返回`null`,用于初始化切片`myslice:= [] int {}` (81认同)
  • 同样要小心:`reflect.DeepEqual`会区分nil切片和非nil切片:`a:= [] int {}`,`var b [] int`,`reflect.DeepEqual(a,b)/ /返回false` (8认同)
  • 在wiki上也提一下https://github.com/golang/go/wiki/CodeReviewComments#declaring-empty-slices (4认同)
  • @КонстантинВан 从 Go 1.16 开始,它们不会生成相同的代码,正如您在[此处](https://godbolt.org/z/Gj7so7ETx)看到的那样。即使对于零长度切片,使用 _make_ 也会调用 [`runtime.makeslice`](https://golang.org/pkg/runtime/?m=all#makeslice),而空切片文字直接使用 [`runtime.makeslice`](https://golang.org/pkg/runtime/?m=all#makeslice)。 Zerobase`](https://golang.org/pkg/runtime/?m=all#zerobase)。意思是,Go 1.16 中的字面量稍微快一些。 (2认同)

icz*_*cza 54

它们是等价的.看到这段代码:

mySlice1 := make([]int, 0)
mySlice2 := []int{}
fmt.Println("mySlice1", cap(mySlice1))
fmt.Println("mySlice2", cap(mySlice2))
Run Code Online (Sandbox Code Playgroud)

输出:

mySlice1 0
mySlice2 0
Run Code Online (Sandbox Code Playgroud)

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

看到类似的问题:

在golang中使用nil切片和空切片有什么意义?

没有切片与非零切片与Go语言中的空切片


tgo*_*gos 37

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

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

nilempty切片之间的区别

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

[pointer] [length] [capacity]
Run Code Online (Sandbox Code Playgroud)

然后:

nil slice:   [nil][0][0]
empty slice: [addr][0][0] // points to an address
Run Code Online (Sandbox Code Playgroud)

零切片

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

// Create a nil slice of integers.
var slice []int
Run Code Online (Sandbox Code Playgroud)

空切片

当您想要表示空集合时,例如当数据库查询返回零结果时,空切片很有用.

// 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{}
Run Code Online (Sandbox Code Playgroud)

不管您使用的是零片或空片,内置的功能append,lencap工作一样.


去游乐场的例子:

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))

}
Run Code Online (Sandbox Code Playgroud)

打印:

true 0 0
false 0 0
Run Code Online (Sandbox Code Playgroud)


Joe*_*.CK 13

在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
Run Code Online (Sandbox Code Playgroud)

对于所有三个切片,len和cap为0.