比如 slice 的 append,按我的理解:
1,扩容就生成新的底层数组,修改新的 slice 不会影响原来底层数组;
2,不扩容就不会生成新的数组,修改新的 slice 会修改原来的底层数组;
觉得这种问题很容易掉坑,求教有什么好习惯可以避免掉坑。
比如 slice 的 append,按我的理解:
1,扩容就生成新的底层数组,修改新的 slice 不会影响原来底层数组;
2,不扩容就不会生成新的数组,修改新的 slice 会修改原来的底层数组;
觉得这种问题很容易掉坑,求教有什么好习惯可以避免掉坑。
|
dongiskingNov 7, 2018
1
另外一个坑
|
|
cheshireNov 7, 2018 via Android
2
初始化的时候能知道大小最好,不然的话指定一个比较大的 capacity
|
|
3
@dongisking 这个结果是唯一的吧,会有第二种情况吗
|
|
brucewuioNov 7, 2018
5
其实《 The Go Programming Language 》 说的挺清楚的 上面也说尽量用数组的抽象 slice 很少直接用数组 加操作直接 append 减操作就[x:y] 截取
|
|
anonymous256Nov 7, 2018
6
这里有个不错的坑,参见: https://www.golangtc.com/t/5565344ab09ecc3d42000026
```golang var dynaArr []string dynaArr = append(dynaArr, "one") dynaArr = append(dynaArr, "two") dynaArr = append(dynaArr, "three") fmt.Println(dynaArr) ``` 这样写就好 |
|
sirgodNov 7, 2018
7
多踩几次坑就好了
|
|
zhujinliangNov 7, 2018
8
@goofool 通常情况下接收方都是作为消费者,只需读取数据,不需修改数据
如果函数不返回数组切片,就不要修改其内容 如果调用函数是为了获得一个数组的返回,那让函数自行 make,然后返回数组: func getSlice() []int { s := make([]int, ...) // 在这个函数内部创建 /// return s } outS := getSlice() 如果函数既需要读取数组里的内容,又需要修改这个数组里的数据或追加数据,让函数接收一个数组同时返回一个数组 func modifySlice(s []int) []int { s = append(s, ...) return s } outS = modifySlice(outS) |
|
10
|
|
11
slice 本身是一个结构体,里面有三个字段:当前 slice 第一个元素在底层数组的指针、slice 长度和 slice 容量。创建 slice 就是基于底层数组生成一个这样的结构体,append 的扩容就是新申请原底层数组一倍的内存,再把原底层数组的内容拷贝过来。大部分时候你不需要关心是否扩容,只要记住 slice 是指类型,作为参数传递会拷贝就行了
```golang type slice struct { array unsafe.Pointer len int cap int } ``` 推荐阅读: https://research.swtch.com/godata |
|
12
最近用 gopacket 这个包,里面有个类似的 Data()方法实现
https://gist.github.com/goofool/4f9e3514a65a97ffa9f0a5eb273fa1fb 结果: https://gist.github.com/goofool/1bfa9898dc6495c64d7120f970278db9 |
|
lrz0lrzNov 7, 2018
13
@dongisking #1 这个坑好像 JS 的
|
|
asAnotherJackNov 7, 2018
16
好巧,几十分钟前也刚看到这儿,看 reader 的 read 方法时想到的这个问题,马一下等 v 友的解答
|
|
tiedanNov 7, 2018
17
@dongisking 对切片进行切片操作产生的是新的切片,不会影响原来的切片
|
|
traitNov 7, 2018
18
如果这么容易引起无意操作,没有人提 issue 要求官方给个解决方案么
|
|
dongiskingNov 7, 2018
20
@tiedan 原来是这样
|