为了使切片追加操作更快,我们需要分配足够的容量.追加Slice有两种方式,代码如下:

func BenchmarkSliceAppend(b *testing.B) {
    a := make([]int, 0, b.N)
    for i := 0; i < b.N; i++ {
        a = append(a, i)
    }
}

func BenchmarkSliceSet(b *testing.B) {
    a := make([]int, b.N)
    for i := 0; i < b.N; i++ {
        a[i] = i
    }
}

结果是:

基准-4 200000000 7.87 ns/op 8 B/op 0 allocs/op

基准切片集-4 300000000 5.76 ns/op 8 B/op

为什么a[i] = ia = append(a, i)快?

推荐答案

a[i] = i只是将值i赋值给a[i].这是not追加,只是一个简单的assignment.

现在追加:

a = append(a, i)

理论上,会发生以下情况:

  1. 这将调用内置append()函数.为此,它首先必须复制a片(片标题,后备数组不是标题的一部分),并且它必须为将包含值i的可变参数创建临时片.

  2. Then it has to reslice a if it has enough capacity (it has in your case) like a = a[:len(a)+1] - which involves assigning the new slice to a inside the append().
    (If a would not have big enough capacity to do the append "in-place", a new array would have to be allocated, content from slice copied, and then the assign / append be executed - but it is not the case here.)

  3. 然后将i指定给a[len(a)-1].

  4. 然后从append()返回新切片,这个新切片被分配给局部变量a.

与简单的任务相比,这里发生了很多事情.即使这些步骤中的许多步骤被优化和/或内联,作为对片the local variable 101 of slice type(其为片首部)has to be updated in each cycle of the loop的元素赋值i的最小附加.

推荐阅读量:The Go Blog: Arrays, slices (and strings): The mechanics of 'append'

Go相关问答推荐

按键值排序字符串- Golang

切换选项卡时,Goland IDE中的光标自动转移

转到http服务器头内容-类型设置为多部分/表单-数据,但在客户端获取内容-类型:文本/纯文本

如何将 goose 迁移与 pgx 一起使用?

使用Dockertest进行Golang SQL单元测试的基本设置

如何忽略打印达到最大深度限制 go colly

如何在 fyne-io/fyne 中设置文本的字母间距?

Golang 中的泛型类型转换

Get 请求在 Thunder 客户端/Postman 中返回数据,但在 Golang 代码中给出空白数据

使用 Grafana alert 在几分钟内重复alert

Golang 通过接口反映/迭代{}

访问传递给可变参数函数的通用 struct 的特定字段

拆分文本并按空格获取字符串数组,如果文本长度超过 500,则获取字符串数组

使用 AppID 在 Windows 中启动应用程序并获取 pid

为什么时间很短.睡眠时间比基准测试中要求的(约 300 ns)长?

Golang grpc go.mod 问题

无限期运行 Go routine (完成后重新启动)

通用函数与外部包中的常见成员一起处理不同的 struct ?

Go 赋值涉及到自定义类型的指针

如何使用 fyne 避免 GUI 应用程序中的循环依赖?