美文网首页
go不同版本slice append后竟然执行结果不一样

go不同版本slice append后竟然执行结果不一样

作者: robertzhai | 来源:发表于2023-02-16 07:50 被阅读0次
    package main
    import (
        "fmt"
    )
    func AddElement(slice []int, e int) []int {
        return append(slice, e)
    }
    func main() {
        var slice []int
        slice = append(slice, 1, 2, 3)
        fmt.Println("before AddElement cap slice:", cap(slice))
        newSlice := AddElement(slice, 4)
        fmt.Println("after AddElement cap newSlice :", cap(newSlice))
        fmt.Println(&slice[0] == &newSlice[0])
    }
    

    版本差异

    go1.13.15 darwin/amd64 执行返回 true

    before AddElement cap slice: 4
    after AddElement cap newSlice : 4
    true
    

    go 1.17 执行返回 false

    before AddElement cap slice: 3
    after AddElement cap newSlice : 6
    false
    

    结论

    slice 动态数组扩容算法不同的版本略有差异

    一次添加多个元素时,本例是3个, go 13 是一个一个添加,扩容(0->1->2->4),go17 是一次加3个(0->3->6),整体还是 <1024 每次2倍,>=1024 每次 1.25倍
    
    
    

    使用append()向切片追加元素时有可能触发扩容,扩容后将会生成新的切片


    image.png
           newcap := old.cap
        doublecap := newcap + newcap
        if cap > doublecap {
            newcap = cap
        } else {
            if old.cap < 1024 {
                newcap = doublecap
            } else {
                // Check 0 < newcap to detect overflow
                // and prevent an infinite loop.
                for 0 < newcap && newcap < cap {
                    newcap += newcap / 4
                }
                // Set newcap to the requested cap when
                // the newcap calculation overflowed.
                if newcap <= 0 {
                    newcap = cap
                }
            }
        }
    

    扩容示例

    image.png

    Go 1.18 又有不同

    ref

    https://www.bookstack.cn/read/GoExpertProgramming/chapter01-1.2-slice.md

    相关文章

      网友评论

          本文标题:go不同版本slice append后竟然执行结果不一样

          本文链接:https://www.haomeiwen.com/subject/rsdhkdtx.html