go 中的slice与数组,slice的append与扩容

转载:https://www.cnblogs.com/JenningsMao/p/9327758.html

一直没发现数组与slice的区别,发现数组的命名是[...] int或[3]int,即前面的[]要有东西,而slice直接是[]int,或者make([]int)

append一定要有返回值,

当len = = cap时 append会导致扩容,底层数组不再共享,

在1024字节以内,扩容一倍,大于2014时,增加cap的1/4

 

go中的数组与C语言中的数组类似,但是不同的是C中的数组名其实还是指针,在作为参数传递的过程中会退化为指针,而go语言则是在编译期间就确定其大小,然后始终是作为值传递的。

初始化

  • [5] int {1,2,3,4,5}
    长度为5的数组,其元素值依次为:1,2,3,4,5
  • [5] int {1,2}
    长度为5的数组,其元素值依次为:1,2,0,0,0 。在初始化时没有指定初值的元素将会赋值为其元素类型int的默认值0,string的默认值是""
  • [...] int {1,2,3,4,5}
    长度为5的数组,其长度是根据初始化时指定的元素个数决定的
  • [5] int { 2:1,3:2,4:3}
    长度为5的数组,key:value,其元素值依次为:0,0,1,2,3。在初始化时指定了2,3,4索引中对应的值:1,2,3
  • [...] int {2:1,4:3}
    长度为5的数组,起元素值依次为:0,0,1,0,3。由于指定了最大索引4对应的值3,根据初始化的元素个数确定其长度为5

作为参数传递

例如:

package main

import (
    "fmt"
    "reflect"
)

func modifySlice(array []int) {
    array[0] = 10
}

func modifyArr(array [5]int) {
    array[0] = 10
}

func modifyPt(array *[5]int){   // 作为指针传递
    (*array)[0] = 10
}

func main(){
    arr := [...]int{1,2,3,4,5}
    fmt.Println(reflect.TypeOf(arr))
    modifyArr(arr)
    fmt.Println("In main(), arr values:", arr)
    modifyPt(&arr)
    fmt.Println("In main(), arr values:", arr)

    sli := []int{1,2,3,4,5}
    fmt.Println(reflect.TypeOf(sli))
    modifySlice(sli)
    fmt.Println("In main(), sli values:", sli)
}

// 输出结果为
//[5]int
//In main(), arr values: [1 2 3 4 5]
//In main(), arr values: [10 2 3 4 5]
//[]int
//5
//In main(), sli values: [10 2 3 4 5]

slice 切片

从上面的例子中可以看出slice作为参数传递的是指针,因此传递速度会快很多。

但是数组作为一个固定长度的数据类型,在使用中有很多不方便的地方,因此go提供了一个很类似python 中的list的数据类型slice

从名字也能看出来slice支持切片操作

sli := []int{1,2,3,4,5}
sli = sli[:3]

还支持append操作

sli = append(sli, 6)
sli = append(sli, sli2)

如果要实现类似数组的值传递的功能,可以利用 copy 函数

sli1 := make([]int, len(sli))
copt(sli1, sli)

初始化

  • 可以通过make初始化
sli := make([]int, 5, 10)  // 5 是其长度,10 是其容量(可选),分别可以通过 len(sli)  cap(sli) 获取
  • 直接初始化(初始长度为0)
var sli []int      // sli = nil
  • 从数组或slice初始化
sli := arr[:]     // sli 的修改也会影响到arr

对比

从上面的内容可以看出数组与切片有以下区别

  • 数组定长,定义的时候就需要确定,切片不定长
  • 切片支持append、copy、切片操作
  • 数组作为参数的时候是默认进行拷贝,值传递,而切片是引用传递

顺便说一下,slice的数据结构类似下面:

+--------------------+
| data pointer |
+--------------------+
| len |
+--------------------+
| cap |
+--------------------+

然后扩容方式与vector类似,1024字节以下是每次cap增加一倍,1024以上是每次cap增加1/4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值