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
函数。