【Golang】来几道题以加强切片知识
Golang中出场率最高的数据类型是切片,切片是基于数组类型做的一层封装的 引用类型。它非常灵活,支持自动扩容。
下面我们做几道切片题:
1.第一题
切片表达式
切片的底层就是一个数组,所以我们可以基于数组通过 切片表达式 得到想要的切片。
func main(){
array := [...]int{1, 2, 3, 4, 5}
s1 := array[:2] //左开右闭(x) 1 2 3 左闭右开(√) 1,2
s2 := array[2:] //4 5(x) 3 4 5
fmt.Println(s1)
fmt.Println(s2)
}
关键字: 左闭右开 ,索引左闭右开
[1 2]
[3 4 5]
2.第二题
append情景1
通过内置的append()
方法为切片添加元素:
func main(){
array := [...]int{1, 2, 3, 4, 5}
s1 := array[:2]
s2 := array[2:]
s1 = append(s1, 999)
fmt.Println(array)
fmt.Println(s1)
fmt.Println(s2)
fmt.Printf("array:%v len(array):%v cap(array):%v\n", array, len(array), cap(array))
fmt.Printf("s1:%v len(s1):%v cap(s1):%v\n", s1, len(s1), cap(s1))
fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2))
//Consider
}
输出
[1 2 999 4 5]
[1 2 999]
[999 4 5]
array:[1 2 999 4 5] len(array):5 cap(array):5
s1:[1 2 999] len(s1):3 cap(s1):5
s2:[999 4 5] len(s2):3 cap(s2):3
结论
为切片添加元素:
- 一直指向底层的数组不变:所以s1的容量一直都是5;
- 一直指向底层的数组不变:所以数组本身,以及后续切片表达式得到的切片都会发生变化
append情景2
func main(){
array := [...]int{1, 2, 3, 4, 5}
s1 := array[:2]
s2 := array[2:]
s1 = append(s1, 999, 888, 777)
fmt.Println(array)
fmt.Println(s1)
fmt.Println(s2)
fmt.Printf("array:%v len(array):%v cap(array):%v\n", array, len(array), cap(array))
fmt.Printf("s1:%v len(s1):%v cap(s1):%v\n", s1, len(s1), cap(s1))
fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2))
//Consider
}
输出
[1 2 999 888 777]
[1 2 999 888 777]
[999 888 777]
array:[1 2 999 888 777] len(array):5 cap(array):5
s1:[1 2 999 888 777] len(s1):5 cap(s1):5
s2:[999 888 777] len(s2):3 cap(s2):3
结论
为切片添加元素:
- 一直指向底层的数组不变:所以s1的容量一直都是5;
- 一直指向底层的数组不变:所以数组本身,以及后续切片表达式得到的切片都会发生变化
append情景3
func main(){
array := [...]int{1, 2, 3, 4, 5}
s1 := array[:2]
s2 := array[2:]
s1 = append(s1, 999, 888, 777, 666)
fmt.Println(array)
fmt.Println(s1)
fmt.Println(s2)
fmt.Printf("array:%v len(array):%v cap(array):%v\n", array, len(array), cap(array))
fmt.Printf("s1:%v len(s1):%v cap(s1):%v\n", s1, len(s1), cap(s1))
fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2))
//Consider
}
输出
[1 2 3 4 5]
[1 2 999 888 777 666]
[3 4 5]
array:[1 2 3 4 5] len(array):5 cap(array):5
s1:[1 2 999 888 777 666] len(s1):6 cap(s1):10
s2:[3 4 5] len(s2):3 cap(s2):3
结论
为切片添加元素:
- 如果切片append后的长度超越了容量,这时底层数组将会更换,且容量也会相应增加,原有的底层数组保持不变,原有的其他切片表达式也保持不变。
总结论
为切片添加元素:
- 当
append
后,len(slice)≤cap(slice)
,会影响到底层数组,以及其他切片表达式切片。 - 当
append
后,len(slice)>cap(slice)
,会更换底层数组,并不影响原来的数组及其他切片表达式。
3.第三题
看题
func main(){
array := [...]int{1, 2, 3, 4, 5}
s1 := array[:2:2]//=>[0:2:2]
s2 := array[2:]
fmt.Printf("array:%v len(array):%v cap(array):%v\n", array, len(array), cap(array))
fmt.Printf("s1:%v len(s1):%v cap(s1):%v\n", s1, len(s1), cap(s1))
fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2))
//Consider
}
输出
array:[1 2 3 4 5] len(array):5 cap(array):5
s1:[1 2] len(s1):2 cap(s1):2 #切片容量只有2
s2:[3 4 5] len(s2):3 cap(s2):3
完整的切片表达式
a[low : high : max]
//等价于=>
a[low: high]
0 <= low <= high <= max <= cap(a)
,所以s1:=array[:2:6]
就会报错:
invalid slice index 6 (out of bounds for 5-element array)
完整的切片表达式它得到的结果切片的容量设置为 max-low。在完整切片表达式中只有第一个索引值(low)可以省略;它默认为0。
4.思考题
留一道题,把下面当做面试题试试,没有运行环境,手写答案:
func main(){
array := [...]int{1, 2, 3, 4, 5}
s1 := array[:2:2]
s2 := array[2:]
fmt.Println(s1) //[1 2]
fmt.Println(s2) //[3 4 5]
s1 = append(s1, 999)
fmt.Println(array) //? give your answer
fmt.Println(s1) //? give your answer
fmt.Println(s2) //? give your answer
//Consider
}
- 原文作者:Garfield
- 原文链接:http://www.randyfield.cn/post/2021-03-31-slice-advanced/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。