Golang cap 函数
最后修改时间 2025 年 5 月 8 日
本教程将解释如何在 Go 中使用内置的 cap 函数。我们将通过实际容量使用示例来介绍切片和数组的容量。
cap 函数返回 Go 中切片或数组的容量。容量表示底层数组可以容纳的最大元素数量。对于数组,容量始终等于长度。
在 Go 中,cap 主要用于切片,以了解其增长潜力。了解切片的容量有助于优化内存使用和性能。
基本数组容量示例
对于数组,cap 始终返回与 len 相同的值。本示例通过固定大小的数组演示容量。
注意:数组的容量在声明时已固定。
array_cap.go
package main
import "fmt"
func main() {
arr := [5]int{1, 2, 3, 4, 5}
fmt.Println("Array:", arr)
fmt.Println("Length:", len(arr))
fmt.Println("Capacity:", cap(arr)) // Same as length for arrays
}
数组的大小固定为 5,因此长度和容量均为 5。声明后,数组的容量无法更改。
切片容量基础
切片可以在需要重新分配之前增长到其容量。本示例显示了切片容量与长度的不同。
slice_cap.go
package main
import "fmt"
func main() {
s := make([]int, 3, 5) // length 3, capacity 5
fmt.Println("Slice:", s)
fmt.Println("Length:", len(s))
fmt.Println("Capacity:", cap(s))
s = append(s, 4)
fmt.Println("\nAfter append:")
fmt.Println("Length:", len(s))
fmt.Println("Capacity:", cap(s)) // Still 5
}
切片的初始长度为 3,但容量为 5。追加一个元素后,长度变为 4,而容量保持为 5。
追加时的容量增长
当切片超出其容量时,Go 会自动分配一个更大的新数组。本示例演示了追加操作期间容量的增长。
capacity_growth.go
package main
import "fmt"
func main() {
s := make([]int, 0, 2) // length 0, capacity 2
fmt.Printf("Initial cap: %d\n", cap(s))
s = append(s, 1)
s = append(s, 2)
fmt.Printf("After 2 appends cap: %d\n", cap(s))
s = append(s, 3) // Exceeds capacity
fmt.Printf("After 3rd append cap: %d\n", cap(s)) // Capacity doubles
}
当超出初始容量时,Go 通常会使容量加倍。这种增长模式有助于分摊多次追加操作的分配成本。
切片表达式的容量
切片操作对容量的影响不同。本示例说明了切片如何影响容量计算。
slice_expression_cap.go
package main
import "fmt"
func main() {
original := make([]int, 5, 10) // length 5, capacity 10
// Full slice
fmt.Printf("Original cap: %d\n", cap(original))
// Slice from index 2
slice1 := original[2:]
fmt.Printf("Slice from 2 cap: %d\n", cap(slice1)) // 8 (10-2)
// Slice from index 2 to 4
slice2 := original[2:4]
fmt.Printf("Slice 2:4 cap: %d\n", cap(slice2)) // Still 8
}
切片根据起始索引影响容量。容量将等于原始容量减去切片的起始索引。
实际容量使用
了解容量有助于优化切片操作。本示例使用容量进行预分配以提高性能。
preallocate_slice.go
package main
import (
"fmt"
"time"
)
func processWithoutPreallocation(n int) {
start := time.Now()
var s []int
for i := 0; i < n; i++ {
s = append(s, i)
}
elapsed := time.Since(start)
fmt.Printf("Without preallocation: %v\n", elapsed)
}
func processWithPreallocation(n int) {
start := time.Now()
s := make([]int, 0, n) // Preallocate capacity
for i := 0; i < n; i++ {
s = append(s, i)
}
elapsed := time.Since(start)
fmt.Printf("With preallocation: %v\n", elapsed)
}
func main() {
const size = 1000000
processWithoutPreallocation(size)
processWithPreallocation(size)
}
预分配容量可以避免在追加操作期间重复分配。这显著提高了大型切片的性能。
来源
本教程通过数组和切片实际容量使用示例,介绍了 Go 中的 cap 函数。