Go语言中,切片类型是包含三个属性:1.地址(暂且不在本次讨论范围内) 2.长度 3.容量
一.概念说明
- 长度:切片中实际存在元素的数量
- 容量:从切片的起始元素开始到其底层数组中最后一个元素的数量
二.切片生成方式
- 从数组生成一个新的切片
- 从切片生成一个新的切片
- 直接生成一个新的切片
1.从数组生成一个新的切片
测试代码:
package my_test
import "testing"
func TestSliceLenCap(t *testing.T) {
var arr = [5]int{1, 22, 333, 444, 5555}
var s1 = arr[1:3]
t.Log(len(s1), cap(s1))
}
简单分析:
首先简单分析猜测一下切片s1的len和cap
,根据len和cap
的概念说明:len是切片中实际的元素个数,s1是arr截取的,arr[1:3],idx[1]取到,idx[3]取不到,也就是[22,333],所以len是2;cap
是切片起始元素到底层数组最后一个元素,起始元素是22,对应的idx是1,数组arr最后一个元素是5555,对应的idx是4,也就是1-4,总共是4个元素,所以cap
是4
结果验证:
=== RUN TestSliceLenCap
my_test.go:8: [22 333]
my_test.go:9: 2 4
— PASS: TestSliceLenCap (0.00s)
PASS
ok command-line-arguments 0.104s
2.从切片生成一个新的切片
其实和从数组生成一个新的切片效果是类似的,我们直接上测试结果:
测试代码:
package my_test
import "testing"
func TestSliceLenCap(t *testing.T) {
var arr = [5]int{1, 22, 333, 444, 5555}
var s1 = arr[1:3]
var s2 = s1[0:1]
t.Log(s1)
t.Log(len(s1), cap(s1))
t.Log(s2, len(s2), cap(s2))
}
验证结果:
=== RUN TestSliceLenCap
my_test.go:9: [22 333]
my_test.go:10: 2 4
my_test.go:11: [22] 1 4
— PASS: TestSliceLenCap (0.00s)
PASS
ok command-line-arguments 0.083s
整个分析过程与结果与之前的一致。
3.直接声明一个新切片
测试代码
package my_test
import "testing"
func TestSliceLenCap(t *testing.T) {
var s10 = []int{1, 2, 3, 4, 5} //申明的同时初始化
t.Log(s10, len(s10), cap(s10))
s20 := make([]int, 2, 4) //通过make申明
t.Log(s20, len(s20), cap(s20))
}
验证结果:
=== RUN TestSliceLenCap
my_test.go:7: [1 2 3 4 5] 5 5
my_test.go:10: [0 0] 2 4
— PASS: TestSliceLenCap (0.00s)
PASS
ok command-line-arguments 0.104s
三.增删切片对len和cap的影响
测试代码
package my_test
import "testing"
func TestSliceLenCap(t *testing.T) {
s20 := make([]int, 2, 4) //通过make申明
t.Log(s20, len(s20), cap(s20))
s20 = append(s20, 1, 2, 3)
t.Log(s20, len(s20), cap(s20))
s30 := make([]int, 2, 4)
for i := 0; i < 10; i++ {
s30 = append(s30, i)
t.Log(s30, len(s30), cap(s30))
}
}
验证结果:
=== RUN TestSliceLenCap
my_test.go:7: [0 0] 2 4
my_test.go:9: [0 0 1 2 3] 5 8
my_test.go:14: [0 0 0] 3 4
my_test.go:14: [0 0 0 1] 4 4
my_test.go:14: [0 0 0 1 2] 5 8
my_test.go:14: [0 0 0 1 2 3] 6 8
my_test.go:14: [0 0 0 1 2 3 4] 7 8
my_test.go:14: [0 0 0 1 2 3 4 5] 8 8
my_test.go:14: [0 0 0 1 2 3 4 5 6] 9 16
my_test.go:14: [0 0 0 1 2 3 4 5 6 7] 10 16
my_test.go:14: [0 0 0 1 2 3 4 5 6 7 8] 11 16
my_test.go:14: [0 0 0 1 2 3 4 5 6 7 8 9] 12 16
— PASS: TestSliceLenCap (0.00s)
PASS
ok command-line-arguments 0.054s
结果分析:
初始cap是4,len是2(初始为零值0),append3个元素之后,即变成5个元素,但是此时len超过cap了,Go语言中cap小于len之后,cap会双倍扩容,这边就是由原来的4->8
。