Golang切片的帽与透镜

mwecs4sa  于 12个月前  发布在  Go
关注(0)|答案(3)|浏览(97)

在Golang中,一片的cap和len有什么区别?
根据定义:
切片既有长度又有容量。
切片的长度是它包含的元素的数量。
切片的容量是底层数组中元素的数量,从切片中的第一个元素开始计数。

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

字符串
len是否仅表示非空值?

bvhaajcl

bvhaajcl1#

切片是一种抽象,它在底层使用数组。
cap告诉你底层数组的容量。len告诉你数组中有多少项。
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将返回一个容量更大的新切片。在第四次迭代中,你会注意到一个更大的容量和一个新的指针地址。
Play example
我知道你没有问数组和append,但它们是理解切片和内置函数的基础。

zzwlnbp8

zzwlnbp82#

从源代码:

// 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

字符串

eit6fx6z

eit6fx6z3#

简单解释切片是数组的自生长形式,因此有两个主要属性。
Length是切片中所有元素的总数,可以用来循环我们存储在切片中的元素。同样,当我们打印切片时,所有的元素都会被打印出来。
容量是底层数组中没有元素的总和,当你追加更多元素时,长度会增加到容量。之后,任何进一步的追加都会导致容量自动增加(大约两倍),长度增加所追加的元素的数量。
真实的魔法发生在你从一个切片中切出子切片时,所有的实际读/写都发生在底层数组上。所以子切片中的任何变化也会改变原始切片和底层数组中的数据。因为任何子切片都可以有自己的长度和容量。
仔细阅读下面的程序。它是一个golang tour 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]

字符串

相关问题