在Go语言中,
var s []int
和s := make([]int, 0)
有什么区别?我发现两者都可以用,但哪一个更好呢?var s []int
和s := make([]int, 0)
有什么区别?我发现两者都可以用,但哪一个更好呢?简单声明
var s []int
不分配内存并且 s
指向 nil
,
s := make([]int, 0)
分配内存,并使s
指向一个包含0个元素的切片。
通常,如果您不知道确切的用例大小,则第一个选项更符合惯用语。
nil
,而不是空数组。然而,如果使用 make
创建切片,将会返回一个空数组,这通常是期望的效果。 - robinmitravar s []int
)的编组将产生null
,而对空的切片(s := make([]int, 0)
)的编组将产生预期的[]
。 - asgaines除了fabriziom的答案外,你还可以在 "Go Slices:用法和内部机制" 中看到更多示例,其中提到了[]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[]
作为要添加的切片即可。
var p []int
比使用 make
更容易(尽管在 0 容量的情况下,它不会分配任何东西)。就可读性而言,我更喜欢不在这里使用 make
。 - VonCp := []int{}
)。由于我们通常使用 :=
语法来声明大多数变量,因此将其应用到所有地方而不是仅针对切片进行例外处理更为自然。除此之外,试图考虑分配通常会促使人们过早地进行优化。 - Arman Ordookhani刚刚发现一个区别。如果你使用
var list []MyObjects
当您将输出编码为JSON时,您会得到null
。
list := make([]MyObjects, 0)
结果如预期,[]
。
一个更完整的例子(在.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>]
func FilterSliceNil(s []int, fn func(int) bool) []int {
var p []int // == nil
for _, v := range s {
if fn(v) {
p = append(p, v)
}
}
return p
}
func FilterSliceCapSet(s []int, fn func(int) bool) []int {
p := make([]int, 0, len(s)) // Set length=0 and capacity to length of s
for _, v := range s {
if fn(v) {
p = append(p, v)
}
}
return p
}
package main
import (
"testing"
)
var slice = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var f = func(i int) bool {
return i%2 == 0
}
func Benchmark_FilterSliceNil(b *testing.B) {
for i := 0; i < b.N; i++ {
FilterSliceNil(slice, f)
}
}
func Benchmark_FilterSliceCapSet(b *testing.B) {
for i := 0; i < b.N; i++ {
FilterSliceCapSet(slice, f)
}
}
$ go test -bench=. -benchtime=10s
goos: linux
goarch: amd64
pkg: example.com/Shadowing
cpu: 13th Gen Intel(R) Core(TM) i7-13700K
Benchmark_FilterSliceNil-24 157664690 76.96 ns/op
Benchmark_FilterSliceCapSet-24 330690351 36.27 ns/op
PASS
ok example.com/Filter 35.479s
make
的版本完成时间只需要一半。
nil
切片,而第二个创建了一个empty
切片(这是《Go语言实战》一书中使用的术语)。为避免重复回答,您可以查看https://dev59.com/9V4b5IYBdhLWcg3wbA-B#45997533。 - tgogos