前两篇写了 slice 是什麽,以及创建 slice 的基本语法。
这篇就来写 slice 的参数传递以及 append 到底做了什麽。
func pass(arr []int) {
arr[0] = 4
}
a := []int{1, 2, 3}
pass(a)
看了这段程序,我们都知道 slice 的第一个元素被改为 4 了。
这时候就会有人说 slice 是 pass by refernece,但是 go 只有 pass by value,还记得 Day1 理解 golang slice 用法及原理 I 所说的 slice header 吗,其实这个函式传递的是 slice header 的副本。slice 的第一个元素被更动,是因为两个 slice header 指向了共同的 underying array。
看图
再看一段程序
func pass(arr []int) {
arr = []int{4, 5, 6}
}
a := []int{1, 2, 3}
pass(a)
arr 的更改并不会影响 a 的内容,因为两个 slice header 指向不同的 underlying array
如果想让 a 指向不同的 underyling array,应该要传送 slice header 的地址。
func pass(arr *[]int) {
arr = []int{4, 5, 6}
}
a := []int{1, 2, 3}
pass(&a)
先看一些两个基本语法
s := []int{1, 2, 3}
s = append(s, 1)
s1 := []int{1, 2, 3}
s2 := []int{4, 5, 6}
s1 = append(s1, s2...)
简单的一个问题, slice 在 append 过後还指向同一个 underlying array 吗? 还是分配了一块新的?
在回答问题之前,先了解一下 append 的实作概念,Reference 1 给了一个很好的概念范例,这段范例给出了 append 设计的想法 (注意:这只是设计的概念)。(如果不熟 copy 怎麽使用,自己 google 一下罗)
func Append(slice []int, elements ...int) []int {
n := len(slice)
total := len(slice) + len(elements)
if total > cap(slice) {
// Reallocate. Grow to 1.5 times the new size, so we can still grow.
newSize := total*3/2 + 1
newSlice := make([]int, total, newSize)
copy(newSlice, slice)
slice = newSlice
}
slice = slice[:total]
copy(slice[n:], elements)
return slice
}
还记得 Day2 理解 golang slice 用法及原理 II 矿泉水的例子吗,假设想把两瓶水装成一瓶,如果本来瓶子容量够大,把另一瓶水装进来就好。如果装不下,那就去找更大的瓶子,把这两瓶水装进去罗。至於为什麽乘 3 除 2 ,那不重要,这边想表达的意思就是要找比原来两个 slice 加起来还要大的容量。
懂了之後,回答原本的问题就很简单了,答案是不一定。
在测试这项范例之前我一直搞不懂在过去测试的时候我记得 test db 不会清除资料,後来查资料才发现...
号志的操作主要分成四种,我们就做个简单的说明: 1.创建跟删除号志:主要分成create/delet...
嗨大家!昨天跟大家分享一个 library 叫做 SWR,文章在这里~ 今天用 SWR 新增了小功能...
「鲑鱼均,因为一场鲑鱼之乱被主管称为鲑鱼世代,广义来说以年龄和脸蛋分类的话这应该算是一种 KNN 的...
到今天最大的困难,好像变成了想主题要写什麽。 来介绍一下做出一个元件後,基本上可以衍伸的思考可能会有...