go语言中切片与数组的区别

结构区别

  • 数组既是一个固定长度、固定元素类型的数据结构。由于有长度和元素类型,所以数组[2]int和[3]int是不同的两个数组。
  • 数组是不需要主动进行初始化的,相对应的0值会在声明后被赋值。例如,[3]int会被初始化为{0,0,0},[2]bool会被初始化为{false,false}等。
  • 在Go中,数组是值而不是指针。
  • 切片是初始化时未声明长度的可变数据结构,其底层依赖数组。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D4r3CfsD-1677457554414)(en-resource://database/720:0)]

初始化

//数组初始化声明一般有两种。e这种声明不用填长度,编译器会帮你计算这个数。
d := [2]int{11, 22}
e := [...]int{11, 22}
fmt.Println(d == e) // 输出 true

//切片初始化时不需要指定长度
s1 := []int{11, 22, 33} // 切片类型
fmt.Println(s1[:2]) // [11 22] 
fmt.Println(s1[1:2]) // [22]

//初始化新的切片,make可接受3个参数,第1个是切片,第2个是切片的长度,第3个是可选的容量大小
func make([]T, len, cap) []T

扩容

  • 一般我们会使用内部函数append来往切片slice后动态追加元素,当cap不够时,如果reslice后可以放下,那么它会reslice。例如上面的s2,底层的数组足以再追加2个元素。如果不行,那么它会new一个新的底层数组,大小为之前cap的两倍,并将之前的元素复制进去。
s := make([]int, 5)
s = append(s, 6, 7) 
fmt.Println(len(s), cap(s)) // 输出7 10 
s = append(s, 8, 9, 10, 11) 
fmt.Println(len(s), cap(s))//输出11 20

注意:若扩容发生在函数中,很可能导致函数中对于切片的操作结果无法显示在主函数中。

func foo(a []int) {
    a = append(a, 1, 2, 3, 4, 5, 6, 7, 8)
    a[0] = 200
}

func main() {
    a := []int{1,2}
    foo(a)
    fmt.Println(a)
}

在函数foo中,新切片a增加了8个元素,原切片对于的底层数组不够放置这8个元素,因此,申请了新的空间来放置扩充后的底层数组。这个时候新切片和原切片指向的底层数组就不是同一个了。
此时如果仍然期望foo函数的操作能够影响原切片
两种方式:

  • 设置返回值,将新切片返回并赋值给 main 函数中的变量 a。
  • 切片也使用指针方式传参。
func foo(a []int) {
    a = append(a, 1, 2, 3, 4, 5, 6, 7, 8)
    a[0] = 200
    return a
}

func main() {
    a := []int{1,2}
    foo(a)
    fmt.Println(a)
}
//或
func foo(a *[]int) {
    *a = append(*a, 1, 2, 3, 4, 5, 6, 7, 8)
    (*a)[0] = 200
}

func main() {
    a := []int{1,2}
    foo(&a)
    fmt.Println(a)
}

函数传递

  • 数组传递给函数时,go会先复制再传递,不会像其他语言会隐式地将数组变成指针。当然,可以直接传递数组指针,避免无谓的复制。
  • 切片传递给函数时,由于其有一个指向第一个切片元素的指针,因此函数中的修改会直接操作底层数组元素。

内容比较

  • 数组之间可以通过"=="比较,判断两个数组是否有相同元素,但是切片不行。
  • 除了可以通过bytes.Equal来判断两个字节类型的slice是否相等,但是对于其他类型slice就必须展开每个元素进行比较。

空值

  • 一个零值的slice等于nil,一个nil值的slice并没有底层数组。
  • 一个nil值的slice长度和容量都是0,但也有非nil值得slice长度和容量也是0,例如[]int{}或者make([]int,3)[3:]。
  • 与任意类型的nil值一样,我们可以用[]int(nil)类型转换表达式来生成一对应类型slice的nil值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值