首页 > 后端开发 > Golang > 为什么重新切片 Go 切片会导致意外的容量值?

为什么重新切片 Go 切片会导致意外的容量值?

Barbara Streisand
发布: 2024-12-24 10:44:13
原创
600 人浏览过

Why Does Re-Slicing a Go Slice Result in Unexpected Capacity Values?

Golang 中的重新切片

理解切片的行为可能会令人困惑,尤其是在涉及重新切片时。在此代码段中:

package main

import "fmt"

func main() {
    a := make([]int, 5)
    printSlice("a", a)
    b := make([]int, 0, 5)
    printSlice("b", b)
    c := b[:2]
    printSlice("c", c)
    d := c[2:5]
    printSlice("d", d)
}

func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
        s, len(x), cap(x), x)
}
登录后复制

输出显示出意外的结果:

a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0] 
d len=3 cap=3 [0 0 0]
登录后复制

为什么 c 的容量为 5 而不是 2?要回答这个问题,我们需要了解 Golang 中切片的概念。

切片是对数组的轻量级引用。当我们创建切片时,我们提供范围操作(例如,[:2])来指定引用数组的开始和结束索引。但是,此范围操作不会创建基础数组的副本。相反,它会创建一个共享相同基础数据的新切片。

在给定的示例中,b 是一个容量为 5 的空切片。当我们将 c 创建为 b 的切片,范围为 [ :2],我们本质上是创建对 b 的前两个元素的引用。由于 b 的容量为 5,因此 c 可以扩展为最多包含 5 个元素,即使当前仅引用 2 个元素。这就是为什么 c 的容量为 5,尽管它的长度为 2。

此外,当我们将 d 创建为范围为 [2:5] 的 c 的切片时,我们实际上是在创建一个共享的切片与 b 相同的基础数据,但从索引 2 开始一直延伸到索引 5。由于 b 的容量为 5,因此 d 的容量为 3 (5-2).

下面的程序更清楚地说明了这种行为:

func main() {
    b := make([]int, 0, 5)
    c := b[:2]
    d := c[1:5] // equivalent to d := b[1:5]
    d[0] = 1
    printSlice("c", c)
    printSlice("d", d)
}
登录后复制

输出:

c len=2 cap=5 [0 1] // modifying d has modified c
d len=4 cap=4 [1 0 0 0] 
登录后复制

如您所见,修改 d 也可以修改了 c,证明 c 和 d 都是同一底层数组 b 上的窗口。

以上是为什么重新切片 Go 切片会导致意外的容量值?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板