最重要的一张图
endlessSummer :=summer[:5]//这是这张图真正厉害的地方
为什么向函数传递slice允许在函数内部修改底层数组的元素?
因为slice值包含指向第一个sllice元素的指针,传入的slice允许在函数内部修改底层数组的元素。
复制的slice只是对底层的数组创建了一个新的slice别名
// reverse reverses a slice of ints in place.
func reverse(s []int) {for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {s[i], s[j] = s[j], s[i]}
}
这个函数是对传入的切片做真实的翻转
slice并没有指明序列的长度,从声明就可以看得出来
s := []int{0,1,12,34,3,4}
slice不能比较,数组可以比较:数组的类型和数值都相同的时候才可以相等
除了byte类型的slice可以进行比较:bytes.Equal
对其他类型只能进行逐一比较
func equal(x,y []string) bool{if len(x)!= len(y){return false}for i:=range x{if x[i]!=y[i]{return false}}return true
}
一个零值的slice等于nil,一个nil值的slice并没有底层数组
var s []int
s = nil
s = []int(nil)
但是一个slice为空,不等于它为nil
我们使用len(s) == 0来判断数组是否为空
一个nil值的slice的行为和其他任意0长度的slice是一样的
reverse(nil)是正确的
看下面这个make语法
make([]T,len)
make([]T,len,cap)
这里的话如果我们没有指出cap,cap = len,在第二个语句中,slice只引用了底层数组前len个元素
append 函数
最重要的一个代码就是容量的扩张
func main() {var x, y []intfor i := 0; i < 10; i++ {y = appendInt(x, i)fmt.Printf("%d cap=%d\t%v\n", i, cap(y), y)x = y}
}
每一次容量的变化都会导致重新分配内存和copy操作:
0 cap=1 [0]
1 cap=2 [0 1]
2 cap=4 [0 1 2]
3 cap=4 [0 1 2 3]
4 cap=8 [0 1 2 3 4]
5 cap=8 [0 1 2 3 4 5]
6 cap=8 [0 1 2 3 4 5 6]
7 cap=8 [0 1 2 3 4 5 6 7]
8 cap=16 [0 1 2 3 4 5 6 7 8]
9 cap=16 [0 1 2 3 4 5 6 7 8 9]
slice模拟stack ,了解一下
入栈:
stack = append(stack,v)
slice顶部位置对应slice的最后一个位置
top := stack[:len(stack)-1]
出栈:
stack = stack[:len(stack)-1]
删除slice中间元素
func remove(slice []int,i int) []int{copy(slice[i:],slice[i+1:])return slice[:len(slice)-1]
}