美文网首页Go
Go陷阱之切片扩容

Go陷阱之切片扩容

作者: Dakini_Wind | 来源:发表于2021-04-20 10:57 被阅读0次

go语言的切片实在是好用,但如果不了解它的坑,代码分分钟变为火葬场。
这里记录一下切片扩容所可能犯的错误。

1. 函数中的切片扩容

func Append(nums []int, a int) {
    nums = append(nums, a)
}

func main() {
    nums := []int{1, 2, 3}
    Append(nums, 4)
    fmt.Println(nums)
}

output:

[1 2 3]

解析:

当切片存储容量不足时,则会把当前切片进行扩容并产生新的切片。新的切片具有新的地址,但是go是按值传递,所以新的切片地址只是局部变量,是不能够随着函数返回的。
若切片容量足够,切片作为函数传参扩容后返回的还是原来的切片内容。因为决定切片的还有len

其他:

func Set(nums []int) {
    nums[0] = 999
}

func main() {
    nums := make([]int, 3, 4)
    nums[2] = 2
    Set(nums)
    fmt.Println(nums)
}

output:

[999 0 2]

解析:

切片作为参数传递时,传递的本质还是指向实际存储的数组的地址,所以还是能够改变值的。只是在进行append操作时需要注意。

2. append后赋值给匿名变量

func main() {
    nums := []int{1, 2, 3}
    _ = append(nums, 4)
    fmt.Println(nums)
}

output:

[1 2 3]

解析:

append产生一个新切片,但是因为赋值给了匿名变量,所以不会影响原变量。

3. 空切片

func main() {
   var errs []error
   errs = append(errs, nil)
   fmt.Println(errs)
}

output:

[<nil>]

解析:

nil也是一个值,可以对数组进行追加。需要注意的是实际使用时可能存在风险。

4. 对同一个数组进行多次append操作

dfs相关算法中会经常进行这种操作,需要额外注意。

func main() {
    x := make([]int, 0, 10)
    x = append(x, 1, 2, 3)
    y := append(x, 4)
    z := append(x,5)
    fmt.Println(x)
    fmt.Println(y)
    fmt.Println(z)
}

output:

[1 2 3]
[1 2 3 5]
[1 2 3 5]

解析:

数组xcap为10,在进行append操作后,len变为3。
再在x上进行 append 4 赋值给y,此时因为xcap大于4,所以不需要进行扩容,会在x的基础上进行追加。即xy实际用于存储的数组指向同一块内存。
此时 y为[1 2 3 4],但此时x为[1 2 3],因为决定切片的还有len,尽管内存中实际存储的还有4。
再在x上进行 append 5 赋值给zx这块内存数组的第4位将存为5,覆盖原来的4(因为xlen为3,append的为第4位)。
这时候x依然受len影响不会变,z变为[1 2 3 5]。此时,xyz实际进行存储的数组指向了同一块内存。所以z进行append时会影响y,此时y也为[1 2 3 5]。

相关文章

  • Go陷阱之切片扩容

    go语言的切片实在是好用,但如果不了解它的坑,代码分分钟变为火葬场。这里记录一下切片扩容所可能犯的错误。 1. 函...

  • 第03天(复合类型)_04

    18_切片和底层数组关系.go 19_append函数的使用.go 20_append扩容特点.go 21_cop...

  • slice

    切片的当前长度和最大容量 切片的扩容算法和内存对齐机制 一般而言,切片是一种操作,切分后获取新的数据对象。但Go中...

  • 切片Slice

    切片 slice的内存分析和扩容 超出容量之后扩容会改变切片底层引用的数组的地址,每次扩容成倍扩容 在已有数组上直...

  • go之slice

    slice中文切片的意思,是go独有的类型,底层是数组,可以很方便的进行截取,也支持扩容、拷贝操作 slice 创...

  • Go数组和切片区别

    数组是值传递,切片是引用传递 切片可扩容 切片多一个cap属性 切片底层用数组实现

  • Go语言切片

    // //Go语言切片 // /* // go语言切片是对数组的抽象 // Go 数组的长度不可改变,在特定场景中...

  • Go之Slice(切片)

    内部结构 切片表面上用起来像是一个可变数组,但它其实是一个结构体,内部结构如下: 切片分为三个参数 指针,指向一片...

  • 第03天(复合类型)_03

    13_数组做函数参数.go 14_数组指针做函数参数.go 15_切片的长度和容量.go 16_切片的创建.go ...

  • 15.Go_Slice(切片)

    Go 切片 定义切片 切片初始化 len()和cap()函数 空(nil)切片 切片拦截 append() 和co...

网友评论

    本文标题:Go陷阱之切片扩容

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