Go 切片的扩容规则是怎么样的

切片是动态数组,容量是根据元素动态增加的。

本来想看看源码怎么写的,发现切片追加元素的方法是内置的,看起来还挺麻烦

源码位于 builtin.go 中:

go 复制代码
// The append built-in function appends elements to the end of a slice. If  
// it has sufficient capacity, the destination is resliced to accommodate the  
// new elements. If it does not, a new underlying array will be allocated.  
// Append returns the updated slice. It is therefore necessary to store the  
// result of append, often in the variable holding the slice itself:  
//  
//  slice = append(slice, elem1, elem2)  
//  slice = append(slice, anotherSlice...)  
//  
// As a special case, it is legal to append a string to a byte slice, like this:  
//  
//  slice = append([]byte("hello "), "world"...)  
func append(slice []Type, elems ...Type) []Type

那么,就用简单的方法来推算规则。编写下面的单测代码,循环 100 次,每次追加 1个元素,看看切片的长度和容量的变化规律是什么。

go 复制代码
func TestSliceAppend(t *testing.T) {  
    slice := make([]int, 0)  
    t.Logf("len:%d cap:%d slice:%v", len(slice), cap(slice), slice)  
    for i := 0; i < 100; i++ {  
       slice = append(slice, i)  
       t.Logf("len:%d cap:%d slice:%v", len(slice), cap(slice), slice)  
    }  
}

输出结果:

复制代码
slice_test.go:54: len:0 cap:0 slice:[]
slice_test.go:57: len:1 cap:1 slice:[0]
slice_test.go:57: len:2 cap:2 slice:[0 1]
slice_test.go:57: len:3 cap:4 slice:[0 1 2]
slice_test.go:57: len:4 cap:4 slice:[0 1 2 3]
slice_test.go:57: len:5 cap:8 slice:[0 1 2 3 4]
slice_test.go:57: len:6 cap:8 slice:[0 1 2 3 4 5]
slice_test.go:57: len:7 cap:8 slice:[0 1 2 3 4 5 6]
slice_test.go:57: len:8 cap:8 slice:[0 1 2 3 4 5 6 7]
slice_test.go:57: len:9 cap:16 slice:[0 1 2 3 4 5 6 7 8]
slice_test.go:57: len:10 cap:16 slice:[0 1 2 3 4 5 6 7 8 9]
slice_test.go:57: len:11 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10]
slice_test.go:57: len:12 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11]
slice_test.go:57: len:13 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12]
slice_test.go:57: len:14 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13]
slice_test.go:57: len:15 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
slice_test.go:57: len:16 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
slice_test.go:57: len:17 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
slice_test.go:57: len:18 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
slice_test.go:57: len:19 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18]
slice_test.go:57: len:20 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
slice_test.go:57: len:21 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
slice_test.go:57: len:22 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21]
slice_test.go:57: len:23 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22]
slice_test.go:57: len:24 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
slice_test.go:57: len:25 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]
slice_test.go:57: len:26 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25]
slice_test.go:57: len:27 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26]
slice_test.go:57: len:28 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27]
...

这里没有都粘贴过来,容量的规则是每次是原来的 2 倍。

Over!

相关推荐
csxin6 分钟前
Spring Boot 中如何设置 serializer 的 TimeZone
java·后端
@半良人16 分钟前
Deepseek+python自动生成禅道测试用例
开发语言·python·测试用例
一只鲲24 分钟前
48 C++ STL模板库17-容器9-关联容器-映射(map)多重映射(multimap)
开发语言·c++
荔枝爱编程27 分钟前
如何在 Docker 容器中使用 Arthas 监控 Java 应用
java·后端·docker
高松燈32 分钟前
kafka入门和核心概念介绍
后端
喵手34 分钟前
Java中Stream与集合框架的差异:如何通过Stream提升效率!
java·后端·java ee
喵手1 小时前
你知道,如何使用Java的多线程机制优化高并发应用吗?
java·后端·java ee
青梅主码1 小时前
坐标差 1 公分,返工一整天?试试这个转换窍门
后端
cxyxiaokui0011 小时前
别让你的Java对象在内存里躺平!序列化带它看世界
后端·面试
白露与泡影1 小时前
SpringBoot前后端token自动续期方案
spring boot·后端·状态模式