首先要知道在Golang中,切片的底层实际就是数组。
切片的长度指切片中元素的数量,可以使用len()函数查询其切片的长度。
示例1:
package main
import "fmt"
func main(){
slice := []int{1,3,2,6,4}
# 调用len查看长度
length := len(slice)
fmt.Printf("slice01的长度是:%v", length)
}
// 输出结果
// slice的长度是:5
在上面代码中,变量length就是切片的长度(结果是5)
切片的容量是指切片底层数组的长度,可以使用cap()函数查看容量
示例2:
package main
import "fmt"
func main(){
slice := []int{1,3,2,6,4}
// 调用cap查看容量
capacity := cap(slice)
fmt.Printf("slice01的容量是:%v", capacity)
}
// 输出结果
// slice的容量是:5
在上面代码中,变量capacity就是切片的容量(结果也是5)
示例3
package main
import "fmt"
func main(){
// 通过make函数来创建slice, 4表示切片的长度, 10标识切片的容量
slice := make([]int, 4, 6)
length := len(slice)
capacity := cap(slice)
fmt.Printf("slice01的长度是:%v\n", length)
fmt.Printf("slice01的容量是:%v\n", capacity)
}
// 输出结果
// slice01的长度是:4
// slice01的容量是:6
你可以想象成:当执行slice := make([]int, 4, 10)
的时候,程序在底层创建了一个长度为6的数组,切片slice引用了前面4个元素,就生成了slice这个切片,当前切片值是:{0, 0, 0, 0},剩下的2个元素则暂时没有引用。
我们知道,golang中切片和数组的主要区别在于数组是定长的,切片是变长的。但我们在示例3中定义了切片的容量是6,那如果超过6个元素了,将会发生什么呢?
示例4
package main
import "fmt"
func main(){
// 通过make函数来创建slice, 4表示切片的长度, 10标识切片的容量
slice := make([]int, 4, 6)
length := len(slice)
capacity := cap(slice)
fmt.Printf("slice01的长度是:%v\n", length)
fmt.Printf("slice01的容量是:%v\n", capacity)
//第一次向切片slice内添加元素
slice = append(slice, 1)
//打印slice的长度,容量,内存地址(slice[0]的内存地址)
fmt.Printf("\n\n第一次结果:")
fmt.Printf("slice的长度是:%v\n", len(slice))
fmt.Printf("slice的容量是:%v\n", cap(slice))
fmt.Printf("slice的内存地址是:%v\n", &slice[0])
// 第二次向slice内添加元素
slice = append(slice, 1)
//打印slice的长度,容量,内存地址(slice[0]的内存地址)
fmt.Printf("\n\n第二次结果:")
fmt.Printf("slice的长度是:%v\n", len(slice))
fmt.Printf("slice的容量是:%v\n", cap(slice))
fmt.Printf("slice的内存地址是:%v\n", &slice[0])
// 第三次向slice内添加元素
slice = append(slice, 1)
//打印slice的长度,容量,内存地址(slice[0]的内存地址)
fmt.Printf("\n\n第三次结果:")
fmt.Printf("slice的长度是:%v\n", len(slice))
fmt.Printf("slice的容量是:%v\n", cap(slice))
fmt.Printf("slice的内存地址是:%v\n", &slice[0])
}
// slice01的长度是:4
// slice01的容量是:6
// 第一次结果:slice的长度是:5
// slice的容量是:6
// slice的内存地址是:0xc00000e390
// 第二次结果:slice的长度是:6
// slice的容量是:6
// slice的内存地址是:0xc00000e390
// 第三次结果:slice的长度是:7
// slice的容量是:12
// slice的内存地址是:0xc000060060
通过示例4我们可以发现:我们初始化切片长度为4, 容量为6的时候。
当第一次和第二次向切片内添加元素后,只有切片的长度增加,容量和内存地址都没改变
当第三次向切片内添加元素后,长度增加了1,容量变成了之前的2倍,内存地址也发生了改变。
由此我们可以推断出:
**总结:**当切片的元素长度超过了默认的容量之后,程序会重新创建一个底层数组和切片绑定,且新的数组的长度为原来的两倍(切片的容量变成原来的两倍)
示例5
package main
import "fmt"
func main() {
slice := make([]int, 4, 4)
slice2 := make([]int, 4, 5)
// 调用下方定义的test函数
test(slice)
test(slice2)
// 输出两个切片调用test函数后的结果
fmt.Printf("slice的结果: %v\n", slice)
fmt.Printf("slice2的结果: %v\n", slice2)
}
func test(s []int) {
s = append(s, 1)
for i := 0; i < len(s); i++ {
s[i] = 100
}
}
// slice的结果: [0 0 0 0]
// slice2的结果: [100 100 100 100]
切片容量不同,导致了最终结果不同。