普通网友 2015-11-18 14:55
浏览 78
已采纳

Golang:追加或不分配切片

Go's append() function only allocates new slice data, when the capacity of the given slice is not sufficient (see also: https://stackoverflow.com/a/28143457/802833). This can lead to unexpected behavior (at least for me as a golang newbie):

package main

import (
    "fmt"
)

func main() {

    a1 := make([][]int, 3)
    a2 := make([][]int, 3)
    b := [][]int{{1, 1, 1}, {2, 2, 2}, {3, 3, 3}}
    common1 := make([]int, 0)
    common2 := make([]int, 0, 12) // provide sufficient capacity
    common1 = append(common1, []int{10, 20}...)
    common2 = append(common2, []int{10, 20}...)

    idx := 0
    for _, k := range b {
        a1[idx] = append(common1, k...) // new slice is allocated
        a2[idx] = append(common2, k...) // no allocation
        idx++
    }

    fmt.Println(a1)
    fmt.Println(a2) // surprise!!!
}

output:

[[10 20 1 1 1] [10 20 2 2 2] [10 20 3 3 3]]

[[10 20 3 3 3] [10 20 3 3 3] [10 20 3 3 3]]

https://play.golang.org/p/8PEqFxAsMt

So, what ist the (idomatic) way in Go to force allocation of new slice data or more precisely to make sure that the slice argument to append() remains unchanged?

  • 写回答

2条回答 默认 最新

  • dongmu3187 2015-11-19 09:10
    关注

    Thanx for your feedback.

    So the solution to gain control of the memory allocation is to do it explicitely (which remembers me that Go is a more a system language than other (scripting) langs):

    package main
    
    import (
        "fmt"
    )
    
    func main() {
    
        a1 := make([][]int, 3)
        a2 := make([][]int, 3)
        b := [][]int{{1, 1, 1}, {2, 2, 2}, {3, 3, 3}}
        common1 := make([]int, 0)
        common2 := make([]int, 0, 12) // provide sufficient capacity
        common1 = append(common1, []int{10, 20}...)
        common2 = append(common2, []int{10, 20}...)
    
        idx := 0
        for _, k := range b {
            a1[idx] = append(common1, k...) // new slice is allocated
    
            a2[idx] = make([]int, len(common2), len(common2)+len(k))
            copy(a2[idx], common2)      // copy & append could probably be
            a2[idx] = append(a2[idx], k...) // combined into a single copy step
    
            idx++
        }
    
        fmt.Println(a1)
        fmt.Println(a2)
    }
    

    output:

    [[10 20 1 1 1] [10 20 2 2 2] [10 20 3 3 3]]

    [[10 20 1 1 1] [10 20 2 2 2] [10 20 3 3 3]]

    https://play.golang.org/p/Id_wSZwb84

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥35 平滑拟合曲线该如何生成
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集