// 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
}
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
5条答案
按热度按时间niwlg2el1#
简单声明
不分配内存,
s
指向nil
,而分配内存,
s
将内存指向具有0个元素的片。通常,如果您不知道用例的确切大小,那么第一个更符合习惯。
syqv5f0l2#
除了fabriziom的answer,你可以在“Go Slices: usage and internals“中看到更多的例子,其中提到了
[]int
的用途:由于slice的零值(
nil
)的作用类似于零长度slice,因此可以声明一个slice变量,然后在循环中附加到它:这意味着,要追加到切片,您不必首先分配内存:
nil
片p int[]
足以作为要添加的片。i2loujxw3#
只是发现了不同。如果使用
然后将输出编码为JSON,得到
null
。结果为
[]
。mutmk8jj4#
一个更完整的例子(
.make()
中还有一个参数):输出:
或者使用动态类型
slice
:输出:
xlpyo6sf5#
Slice可能会超出其容量,这意味着内存重新分配,这可能是昂贵的(需要一些时间)。有一个关于切片如何增长的规则:
Go切片的大小增加一倍,直到1024,之后每次增加25
现在让我们比较两种方法:
var p []int
p := make([]int, 0, len(s))
下面我们有两个函数,一个只声明切片,另一个使用
make
创建切片并设置其容量。基准测试功能:
基准测试结果:
在我的机器上,使用
make
的版本需要一半的时间才能完成。