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!

相关推荐
Penge66611 小时前
Elasticsearch BKD 树与 PointRangeQuery:为何数值查询会有性能瓶颈
后端
csbysj202011 小时前
DOM 节点
开发语言
木木一直在哭泣12 小时前
【收藏级】Java Stream.reduce 全面解析:从零到通透(原理图 + 实战 + 最佳实践)
后端
Penge66612 小时前
Elasticsearch Filter 缓存:Bitset 如何让查询速度飙升
后端
用户849137175471612 小时前
ThreadLocal 源码深度解析:JDK 设计者的“妥协”与“智慧”
java·后端
木木一直在哭泣12 小时前
Java Stream.filter 全面解析:定义、原理与最常见使用场景
后端
用户03048059126312 小时前
# 【Maven避坑】源码去哪了?一文看懂 Maven 工程与打包后的目录映射关系
java·后端
小尧嵌入式12 小时前
C++基础语法总结
开发语言·c++·stm32·单片机·嵌入式硬件·算法
绫语宁12 小时前
以防你不知道LLM小技巧!为什么 LLM 不适合多任务推理?
人工智能·后端
@游子12 小时前
Python学习笔记-Day2
开发语言·python