正确的初始化空切片的方法是什么?

huangapple go评论89阅读模式
英文:

Correct way to initialize empty slice

问题

声明一个空的切片,且大小不固定,哪种方式更好呢?

是这样做更好:

mySlice1 := make([]int, 0)

还是这样做更好:

mySlice2 := []int{}

只是想知道哪种方式是正确的。

英文:

To declare an empty slice, with a non-fixed size,
is it better to do:

mySlice1 := make([]int, 0)

or:

mySlice2 := []int{}

Just wondering which one is the correct way.

答案1

得分: 453

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

你还可以选择将其保留为nil值:

var myslice []int

正如Golang.org博客中所述:

> 尽管nil切片指向空,但在功能上与零长度切片等效。它的长度为零,可以进行追加分配。

nil切片在进行json.Marshal()时将转换为"null",而空切片将转换为"[]",如@farwayer所指出的。

如@ArmanOrdookhani所指出的,以上任何选项都不会导致任何分配。

英文:

The two alternative you gave are semantically identical, but using make([]int, 0) will result in an internal call to runtime.makeslice (Go 1.16).

You also have the option to leave it with a nil value:

var myslice []int

As written in the 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 slice will however json.Marshal() into "null" whereas an empty slice will marshal into "[]", as pointed out by @farwayer.

None of the above options will cause any allocation, as pointed out by @ArmanOrdookhani.

答案2

得分: 129

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

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

输出结果:

mySlice1 0
mySlice2 0

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

参考类似的问题:

https://stackoverflow.com/questions/49104157/what-is-the-point-of-having-nil-slice-and-empty-slice-in-golang

https://stackoverflow.com/questions/44305170/nil-slices-vs-non-nil-slices-vs-empty-slices-in-go-language/44305910#44305910

英文:

They are equivalent. See this code:

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

Output:

mySlice1 0
mySlice2 0

Both slices have 0 capacity which implies both slices have 0 length (cannot be greater than the capacity) which implies both slices have no elements. This means the 2 slices are identical in every aspect.

See similar questions:

https://stackoverflow.com/questions/49104157/what-is-the-point-of-having-nil-slice-and-empty-slice-in-golang

https://stackoverflow.com/questions/44305170/nil-slices-vs-non-nil-slices-vs-empty-slices-in-go-language/44305910#44305910

答案3

得分: 66

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

以下是我认为值得一提的来自《Go语言实战》一书的一些信息:

nil切片与空切片的区别

如果我们将切片表示为:

[指针] [长度] [容量]

那么:

nil切片:   [nil][0][0]
空切片: [地址][0][0] // 指向一个地址

nil切片

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

// 创建一个整型的nil切片。
var slice []int

空切片

当你想表示一个空的集合时,比如数据库查询返回零结果时,空切片非常有用。

// 使用make创建一个空的整型切片。
slice := make([]int, 0)
// 使用切片字面量创建一个空的整型切片。
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
英文:

As an addition to @ANisus' answer...

below is some information from the "Go in action" book, which I think is worth mentioning:

Difference between nil & empty slices

If we think of a slice like this:

[pointer] [length] [capacity]

then:

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

}

prints:

true 0 0
false 0 0

答案4

得分: 18

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

英文:

Empty slice and nil slice are initialized differently in 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

As for all three slices, len and cap are 0.

答案5

得分: 2

除了 @ANisus 的回答之外,

当使用官方的 Go MongoDb Driver 时,一个 nil 切片也会被编组为 "null",而一个空切片会被编组为 "[]"

当使用社区支持的 MGO driver 时,nil 和空切片都会被编组为 "[]"

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

英文:

In addition to @ANisus' answer

When using the official Go MongoDb Driver, a nil slice will also marshal into "null" whereas an empty slice will marshal into "[]".

When using using the community supported MGO driver, both nil and empty slices will be marshalled into "[]".

Reference: https://jira.mongodb.org/browse/GODRIVER-971

huangapple
  • 本文由 发表于 2015年3月20日 18:27:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/29164375.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定