在 Go 中,切片的底层是一个数组,当切片容量不足时,需要扩容底层数组以容纳更多元素。扩容的方式是创建一个新的底层数组,将原来的元素拷贝到新数组中,然后将新元素追加到新数组的尾部。新的切片会引用新的底层数组,而原来的切片仍然引用原来的底层数组。
扩容的过程中,Go 会根据一定的策略选择新数组的大小。具体来说,如果新元素的数量小于等于原来元素数量的两倍,那么新数组的大小就是原来数组大小的两倍。如果新元素数量大于原来元素数量的两倍,那么新数组的大小就是原来数组大小加上新元素数量。
下面是一个示例代码,演示了切片扩容的过程:
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5}
fmt.Println("len(s) = ", len(s)) // 输出:len(s) = 5
fmt.Println("cap(s) = ", cap(s)) // 输出:cap(s) = 5
s = append(s, 6)
fmt.Println("len(s) = ", len(s)) // 输出:len(s) = 6
fmt.Println("cap(s) = ", cap(s)) // 输出:cap(s) = 10
s = append(s, 7, 8, 9, 10)
fmt.Println("len(s) = ", len(s)) // 输出:len(s) = 10
fmt.Println("cap(s) = ", cap(s)) // 输出:cap(s) = 10
s = append(s, 11)
fmt.Println("len(s) = ", len(s)) // 输出:len(s) = 11
fmt.Println("cap(s) = ", cap(s)) // 输出:cap(s) = 20
}
在上面的代码中,我们使用 append 函数向切片中追加元素。当切片容量不足时,Go 会自动扩容底层数组。我们通过 len 和 cap 函数分别获取切片的长度和容量,可以看到当新元素数量小于等于原来元素数量的两倍时,容量会扩大为原来的两倍。
当新元素数量大于原来元素数量的两倍时,容量会扩大为原来的大小加上新元素数量。在本例中,初始切片容量为 5,当追加第 6 个元素时,容量扩大为 10。当追加 7、8、9 和 10 时,容量保持不变,因为新元素数量小于等于原来元素数量的两倍。当追加第 11 个元素时,容量扩大为 20。