深拷贝与浅拷贝
https://davidchan0519.github.io/2019/04/22/go-slice-copy/
cuishuangtodo
https://juejin.cn/post/7202984088184635447
以及 /Users/fliter/go/src/shuang/slicee/lab
参考:
使用make()构造切片
语法为:
make ([]T, size, cap)
T:切片的元素类型
size:切片中元素的数量
cap:切片的容量
1 | package main |
如果不写容量,则默认长度就是容量。
1 | package main |
切片的比较
切片之间不能比较, 不能使用==操作符来判断两个切片是否含有全部相等元素.
切片唯一合法的比较操作是和nil比较.一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0.
基于数组定义切片 & 基于切片再切片 情况下的各种陷阱
1 | package main |
切片是引用类型,只要它们是从同一个底层”链接”出去的,那其修改操作就会影响底层。
再如:
1 | package main |
输出为:
1 | s的值为: [1 2 3 4 5 6 7 8 9] |
使用copy(深度)拷贝切片
1 | package main |
copy操作之后的切片c和切片a之间没有任何关系 是两个独立的切片
!!!append及切片的扩容策略
1.如果要的容量没有原来容量两倍大, 那就扩充到原来容量的两倍.
2.如果要的容量是原来容量的两倍还要多, 那新的容量就是所要求的容量大小.
3.如果原来的容量大于1024,那么每次提升25%,不再是两倍扩容.
4.还有更复杂的内存对齐问题,可参考 golang中slice扩容一定是double或1.25倍吗
- 双倍
1 | package main |
输出为:
1 | 此时的长度和容量为:111 1 1 |
再如:
1 | package main |
输出为:
1 | 6 |
- 一次压入多个元素, 要的容量大于原容量的两倍,则新容量就是其需要的容量
1 | package main |
- 元素个数大于1024时,变为1.25倍扩容
1 | package main |
!!!扩容时底层数组的变化
fmt包%p打印的这个地址,到底是谁的地址?
1 | //reflect/value.go |
通过分析fmt包的源码,不难发现,打印的地址,其实是切片里指向底层数组的指针存储的地址,并不是这个切片本身的地址
1 | package main |
输出为:
1 | [0] len:1 cap:1 ptr:0xc000016068 |
共享同一个底层数组时,切片2修改值,会影响切片1的值; 当两个切片不再共享一个底层数组时,修改就互不影响.
如下:
1 | package main |
输出为:
1 | [0] len:1 cap:1 ptr:0xc00008c008 |
再如:(原因待解)
1 | func main() { |
输出为:
1 | [1] len:1 cap:1 ptr:0xc00008c008 |
个中原因,//TODO
对 数组/切片 进行排序
可以使用自带的sort包进行排序,但入参必须是切片.所以如果是数组a1排序,要传入其对应的切片a1[:]
1 | package main |
更多关于slice的”黑魔法”,
参考:
原文链接: https://dashen.tech/2010/03/02/golang之slice中的小tips/
版权声明: 转载请注明出处.