go语言扩容方法有哪些
更新时间:2023-12-21什么是扩容
在Go中,slice是一个动态数组,可以动态分配和释放内存。但是,为了提高性能,slice可能会预分配比实际使用更多的空间。如果slice没有足够的空间存储元素,需要先重新分配更大的内存块,将现有元素复制到新的内存块中,然后释放旧内存块。这个过程称为扩容。
默认扩容方法
Go语言规范定义了一个默认的扩容策略,当slice的长度小于1024时,每次扩容将分配2倍的容量;当slice的长度大于等于1024时,则以1.25倍的比例进行扩容。Go语言通过内置函数cap()获取slice的容量,通过append()函数添加元素。
s := make([]int, 5, 10) fmt.Println(len(s)) // 5 fmt.Println(cap(s)) // 10 s = append(s, 1) fmt.Println(len(s)) // 6 fmt.Println(cap(s)) // 10 s = append(s, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) fmt.Println(len(s)) // 24 fmt.Println(cap(s)) // 40
手动设置扩容量
有时候,我们可能需要手动设置slice的扩容量(capacity),以减少内存分配的次数。可以通过内置函数make()的第三个参数来控制slice的容量。
s := make([]int, 5, 10) fmt.Println(len(s)) // 5 fmt.Println(cap(s)) // 10 s = s[:7] // 手动设置为7 fmt.Println(len(s)) // 7 fmt.Println(cap(s)) // 10
扩容后增加固定大小
有些情况下,我们需要在扩容之后增加固定大小的元素个数。我们可以通过把新元素的数量与slice的当前容量相加,来计算需要分配的新内存块的大小。
s := []int{1, 2, 3} fmt.Println(len(s)) // 3 fmt.Println(cap(s)) // 3 n := 5 if len(s)+n > cap(s) { newCap := (len(s) + n) * 2 // 计算需要分配的新内存块的大小 newSlice := make([]int, len(s), newCap) copy(newSlice, s) s = newSlice } s = append(s, 4, 5, 6, 7, 8) fmt.Println(len(s)) // 8 fmt.Println(cap(s)) // 10总结:Go语言中,slice的扩容是一个常见的操作,可以通过append()函数和make()的第三个参数来实现。我们也可以手动设置slice的扩容量,以达到更好的内存管理和性能优化效果。