cap 与 golang 中切片的 len

问题描述 投票:0回答:3

golang 中切片的 cap 和 len 有什么区别?

根据定义:

切片既有长度又有容量。

切片的长度是它包含的元素数量。

切片的容量是底层数组中的元素数量,从切片中的第一个元素开始计算。

x := make([]int, 0, 5) // len(b)=0, cap(b)=5

len 是否仅表示非空值?

go slice
3个回答
196
投票

切片是一种在幕后使用数组的抽象。

Go 中的切片抽象非常好,因为它会为您调整底层数组的大小,而且 Go 中数组无法调整大小,因此几乎总是使用切片。

示例:

s := make([]int, 0, 3)
for i := 0; i < 5; i++ {
    s = append(s, i)
    fmt.Printf("cap %v, len %v, %p\n", cap(s), len(s), s)
}

会输出类似这样的内容:

cap 3, len 1, 0x1040e130
cap 3, len 2, 0x1040e130
cap 3, len 3, 0x1040e130
cap 6, len 4, 0x10432220
cap 6, len 5, 0x10432220

正如您所看到的,一旦满足容量,

append
将返回一个具有更大容量的新切片。在第四次迭代中,您会注意到更大的容量和新的指针地址。

播放示例

我意识到您没有询问数组和附加,但它们对于理解切片和内置函数的原因非常基础。


14
投票

来自源代码

// The len built-in function returns the length of v, according to its type:
//  Array: the number of elements in v.
//  Pointer to array: the number of elements in *v (even if v is nil).
//  Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
//  String: the number of bytes in v.
//  Channel: the number of elements queued (unread) in the channel buffer;
//  if v is nil, len(v) is zero.
func len(v Type) int

// The cap built-in function returns the capacity of v, according to its type:
//  Array: the number of elements in v (same as len(v)).
//  Pointer to array: the number of elements in *v (same as len(v)).
//  Slice: the maximum length the slice can reach when resliced;
//  if v is nil, cap(v) is zero.
//  Channel: the channel buffer capacity, in units of elements;
//  if v is nil, cap(v) is zero.
func cap(v Type) int

4
投票

简单说明 切片是数组的自增长形式,因此有两个主要属性。

长度是切片拥有的元素总数(),可用于循环我们存储在切片中的元素。此外,当我们打印切片时,所有元素直到打印长度为止。

容量是基础数组中没有元素的总和,当您附加更多元素时,长度会增加直到容量为止。之后,对切片的任何进一步附加都会导致容量自动增加(大约双倍)和长度自动增加附加元素的数量。

当您从切片中切出子切片时,真正的魔力就会发生,其中所有实际的读/写都发生在底层数组上。因此,子切片中的任何更改也会更改原始切片和底层数组中的数据。任何子切片都可以有自己的长度和容量。

仔细阅读下面的程序。这是一个 golang 之旅的修改版本example

package main

import "fmt"

func main() {
    sorig := []int{2, 3, 5, 7, 11, 13}
    printSlice(sorig)

    // Slice the slice to give it zero length.
    s := sorig[:0]
    printSlice(s)

    // Extend its length.
    s = s[:4]
    s[2] = 555
    printSlice(s)

    // Drop its first two values.
    s = s[2:]
    printSlice(s)
    
    printSlice(sorig)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}     

//Output
//len=6 cap=6 [2 3 5 7 11 13]
//len=0 cap=6 []
//len=4 cap=6 [2 3 555 7]
//len=2 cap=4 [555 7]
//len=6 cap=6 [2 3 555 7 11 13]
© www.soinside.com 2019 - 2024. All rights reserved.