You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言中:使用copy处理切片是否总是比append更高效?

拼接大切片:append可变参数 vs make+copy的效率对比

你的想法是正确的——append(sl, sl2...)在拼接两个大切片的场景下,效率和make+copy的组合几乎一致,甚至在部分场景下表现更优,完全可以放心用它来保证代码可读性。

为什么append不会多次扩容?

Go语言的append函数在处理append(s, s2...)这种形式时,会直接获取s2的长度,计算出需要的总元素数:len(s) + len(s2)。接下来的内存分配逻辑是:

  • 如果原切片s的剩余容量(cap(s) - len(s))足够容纳s2的所有元素,就直接在原切片的底层数组后追加数据,不需要分配新内存;
  • 如果剩余容量不够,会一次性分配刚好满足总长度的内存(或按Go的扩容策略分配,但不会分多次扩容),然后把原切片和s2的数据一次性复制到新数组中。

和make+copy的本质对比

make+copy的逻辑是预先分配刚好大小的内存,然后分两次把两个切片的数据复制进去。而append在需要扩容时,底层做的是同样的事:一次性分配足够内存,然后批量复制原切片和传入切片的数据。两者的内存操作和复制次数完全一致,性能差异可以忽略不计。

如果原切片本身还有剩余容量,append甚至会更高效——因为它不需要创建新的切片,直接复用原底层数组,而make+copy无论如何都会新建一个切片。

基准测试验证

你可以通过Go的基准测试直观看到两者的性能差异:

func BenchmarkAppendSlice(b *testing.B) {
    sl := make([]int, 10000)
    sl2 := make([]int, 10000)
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        _ = append(sl, sl2...)
    }
}

func BenchmarkMakeCopySlice(b *testing.B) {
    sl := make([]int, 10000)
    sl2 := make([]int, 10000)
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        nsl := make([]int, len(sl)+len(sl2))
        copy(nsl, sl)
        copy(nsl[len(sl):], sl2)
        _ = nsl
    }
}

运行测试后会发现,两者的耗时几乎持平,在原切片有剩余容量的情况下,append的表现还会略好。

总结

在拼接两个大切片时,append(sl, sl2...)既保证了代码的可读性,又不会带来额外的性能开销,你的判断完全正确——它只会进行一次扩容(如果需要的话),效率和手动make+copy相当。

内容的提问来源于stack exchange,提问作者jcquokka88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:01:16