Go专家编程 slice篇

本文详细分析了Go语言中切片的工作原理,包括切片的基本结构、创建方式、扩容策略以及注意事项。作者指出,由于append函数的扩容机制,切片在特定情况下可能共享同一底层数组。在示例代码中,由于初始append操作未达到最大容量,导致第二次append时发生了扩容,使得新旧切片不再共享存储空间,与书中的解释有所出入。此外,文章还强调了切片不可直接比较以及如何正确判断切片是否为空。
摘要由CSDN通过智能技术生成

书上给了一道题

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)
    newSlice := AddElement(slice, 4)
    fmt.Println(&slice[0] == &newSlice[0])
}

书中给出的参考答案:
append函数执行时会判断切片容量是否能够存放新增元素,如果不能,则会重新申请存储空间,新存储空间将是原来的2倍或1.25倍(取决于扩展原空间大小),本例中实际执行了两次append操作,第一次空间增长到4,所以第二次append不会再扩容,所以新旧两个切片将共用一块存储空间。程序会输出”true”。

不知道作者所用的golang+平台是哪个,我用的是go version go1.16.4 linux/arm64

 得出的结果跟作者不同。

slice = append(slice,1,2,3) 这行代码,空间是3 并不是4.。如果是4 就跟书中作者分析的一样,按照实际运行的是3。所以再次append的时候 就扩容了。

一:基本结构

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

从基本结构上可以看出,slice在发生值传递的时候,len和cap是复制了一份的,也就是说可视范围都是独立的。 

二:注意事项

a[low : high : max]    // 0 <= low <= high <= max <= cap(a)

cap = max - low,low和high 是左闭右开

1.1:创建方式

make:        slice := make([]int, 5, 10)

array:        slice := array[5:7]

1.2:copy不会发生扩容

使用copy()内置函数拷贝两个切片时,会将源切片的数据逐个拷贝到目的切片指向的数组中,拷贝数量取两个切片长度的最小值。例如长度为10的切片拷贝到长度为5的切片时,将会拷贝5个元素。也就是说,copy过程中不会发生扩容。

三:扩容策略

参看前边的文章:Golang slice扩容深度分析_zhangdell的专栏-CSDN博客

四:坑

切片之间是不能比较的,不能用==去比较2个切片。切片唯一合法的比较操作是和nil去比较。

一个值为nil的切片是没有底层数组的,它的长度和容量是0。但是我们不能说一个长度和容量是0的切片 一定是nil。比如

var s1 []int         //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{}        //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil

所以判断一个切片是不是空,要用len(s) == 0 不能用s == nil。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值