博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
详解go语言的array和slice 【二】
阅读量:5316 次
发布时间:2019-06-14

本文共 3182 字,大约阅读时间需要 10 分钟。

  上一篇  已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多。上一篇的最后讲解到创建新的slice时使用第三个索引来限制slice的容量,在操作新slice时,如果新slice的容量大于长度时,添加新元素依然后使源的相应元素改变。这一篇里我会讲解到如何避免这些问题,以及迭代、和做为方法参数方面的知识点。

slice的长度和容量设置为同一个值

  如果在创建新的slice时我们把他的长度和容量的值设置为样的值,那么在append新元素时,底层会创建一个新的array并把之前的值复制过去。这样就不会影响之前共同的底层array了。

// 创建一个容量和长度均为6的slice    slice1 := []int{
5, 23, 10, 2, 61, 33} // 对slices1进行切片,长度为2容量为3 slice2 := slice1[1:3:3] fmt.Println("cap", cap(slice2)) fmt.Println("slice2", slice2) //修改一个共同指向的元素 //两个slice的值都会修改 slice2[0] = 11111 fmt.Println("slice1", slice1) fmt.Println("slice2", slice2) // 增加一个元素 slice2 = append(slice2, 55555) fmt.Println("slice1: ", slice1) fmt.Println("slice2: ", slice2)

  输出结果

cap 2slice2 [23 10]slice1 [5 11111 10 2 61 33]slice2 [11111 10]slice1:  [5 11111 10 2 61 33]slice2:  [11111 10 55555]

  代码中的长度和容量是一样的,长度和容量的计算公式看我的上一篇博客。增加一个元素后,原来共同指向的底层数据是没有变的。因为slice2的底层array被重新赋值了。

迭代slice

  go语言内置一个关键字range用于迭代集合,当然他也可以迭代slice,也可以使用  _  来忽略我们不关心的元素,但是如果只关心index则不需这么写 for index,_ := range slice1。下在给出完整代码

// 创建一个容量和长度均为6的slice    slice1 := []int{
5, 23, 10, 2, 61, 33} for index, value := range slice1 { fmt.Println("index: ", index, " value: ", value) } // 可以忽略我们不关心的元素 // 只关心value for _, value := range slice1 { fmt.Println("value ", value) } // 只关心index, 可以不用 _ for index := range slice1 { fmt.Println("index: ", index) }

 

   需要注意的是rang 迭代的value值并是一个复本,我们可以对比一下迭代的value和原slice内相应index下value的地址:

// 创建一个容量和长度均为6的slice    slice1 := []int{
5, 23, 10, 2, 61, 33} for index, value := range slice1 { fmt.Println("index: ", index, " value address : ", &value, " slice1 value address", &slice1[index]) }

  输出结果

index:  0  value address :  0xc04204e088  slice1 value address 0xc04206a030index:  1  value address :  0xc04204e088  slice1 value address 0xc04206a038index:  2  value address :  0xc04204e088  slice1 value address 0xc04206a040index:  3  value address :  0xc04204e088  slice1 value address 0xc04206a048index:  4  value address :  0xc04204e088  slice1 value address 0xc04206a050index:  5  value address :  0xc04204e088  slice1 value address 0xc04206a058

  slice1中value的地址是不断变化的。而迭代的value值的地址没有变化,这是因为value是一个变量,为次迭代的时候赋不同的值。我们把代码写成下面这样,你就清楚了

var index, value int    for index, value = range slice1 {        fmt.Println("index: ", index, &index, " value address : ", &value, " slice1 value address", &slice1[index])    }

   除了使用rang 也可以使用传统的for循环来做迭代

slice1 := []int{
5, 23, 10, 2, 61, 33} for i, len := 1, len(slice1); i < len; i++ { fmt.Println("index: ", i, " value:", slice1[i]) }

 

 slice作为方法参数

   由于slice的特殊结构,有一个指针指向一个数组

s := make([]int, 2, 5)    fmt.Println("len: ", len(s))    fmt.Println("cap: ", cap(s))    s = append(s, 2)    s[0] = 12

 

  所以,slice做为方法的参数传递时,只会复制slice本身而不会复制slice底层的array.如果我们创建一个int类型有100万长度的slice ,把他传递给一个方法时,只需要复制24个字节就够了。指针需要8个,长度和容量都是8个。

const size int = 1000 * 1000func main() {    slice0 := make([]int, size)    fmt.Println("slice0 len: ", len(slice0), " cap :", cap(slice0))    doSomeThing(slice0)}func doSomeThing(s []int) {    fmt.Println(len(s))}

 

 

转载于:https://www.cnblogs.com/li-peng/p/7541554.html

你可能感兴趣的文章
云计算数据与信息安全防护
查看>>
RxJS & Angular
查看>>
面向对象(多异常的声明与处理)
查看>>
MTK笔记
查看>>
ERROR: duplicate key value violates unique constraint "xxx"
查看>>
激活office 365 的启动文件
查看>>
无法根据中文查找
查看>>
[简讯]phpMyAdmin项目已迁移至GitHub
查看>>
转载 python多重继承C3算法
查看>>
【题解】 bzoj1597: [Usaco2008 Mar]土地购买 (动态规划+斜率优化)
查看>>
css文本溢出显示省略号
查看>>
git安装和简单配置
查看>>
面向对象:反射,双下方法
查看>>
鼠标悬停提示文本消息最简单的做法
查看>>
Java面向对象重要关键字
查看>>
课后作业-阅读任务-阅读提问-2
查看>>
面向对象设计中private,public,protected的访问控制原则及静态代码块的初始化顺序...
查看>>
fat32转ntfs ,Win7系统提示对于目标文件系统文件过大解决教程
查看>>
Awesome Adb——一份超全超详细的 ADB 用法大全
查看>>
shell cat 合并文件,合并数据库sql文件
查看>>