为什么一个空切片的切片表达式中会有值?

huangapple go评论115阅读模式
英文:

Why does a slice expression of an empty slice have values in it?

问题

刚开始学习Golang,对切片表达式有些困惑。

这段代码的输出结果是:

[] [20] [20 0] [20 0]

我对这段代码的理解如下:

  • x := make([]int, 0, 5) - 创建一个新的 int 类型切片,长度为 0,容量为 5。

  • y := append(x, 20) - 使用 append 函数创建一个新的切片,长度为 1,容量为 5,y 的值为 [20]

  • fmt.Println(x, y, x[:2], y[:2])

    • x[:2] 为什么输出 [20 0]?它不应该导致错误吗?如果这是一个切片表达式创建一个新的切片,它不应该是 [0 0] 吗?第一个值为什么是 20?

我在这里可能缺少一些基本概念。

如果我要猜测的话,我认为使用 y := append(x, 20) 创建的 y 切片与底层数组共享内存。当我直接打印 x 时,这一点并不明显,但当我打印 x[:2] 时就能看到。

英文:

Just started leaning Golang. Facing some trouble understanding the slice expression.

package main

import "fmt"

func main() {
	x := make([]int, 0, 5)
	y := append(x, 20)
	fmt.Println(x, y, x[:2], y[:2])
}

Output:

[] [20] [20 0] [20 0]

Here's my understanding of what this represents:

  • x := make([]int, 0, 5) - make a new slice of ints with 0 length and 5 capacity.

  • y := append(x, 20) - create a a new slice using append function with length 1 & capacity of 5. y is [20].

  • fmt.Println(x, y, x[:2], y[:2])

    • How does x[:2] print [20 0]? Shouldn't it just cause an error? If this was the slice expression creating a new slice shouldn't it be [0 0]? How is the first value 20?

I am missing some fundamental concept here.

If I were to take a guess I think creating y using y := append(x, 20) is somehow sharing the underlying memory. This is not shown when I print x directly, but when I am printing x[:2] it is shown.

答案1

得分: 3

> y := append(x, 20) - 使用append函数创建一个新的切片,长度为1,容量为5。y为[20]。

这是不正确的。因为已经有可用的容量,所以它不会分配一个新的数组。这就是预先分配容量大于长度的切片的整个目的。

x := make([]int, 0, 5)

会生成一个切片[],底层数组为[0, 0, 0, 0, 0]。

y := append(x, 20)

会生成一个切片[20],底层数组仍为[20, 0, 0, 0, 0]。

fmt.Println(x, y, x[:2], y[:2])

会产生四个切片:

x = [] //(长度和容量未改变)
y = [20] //(参见上面的append解释)
x[:2] = [20, 0] //(底层数组的前两个元素)
y[:2] = [20, 0] //(同一个数组的相同两个元素)

这在Go之旅Go博客中有详细介绍。

英文:

> y := append(x, 20) - create a a new slice using append function with length 1 & capacity of 5. y is [20].

Not true. Because there is capacity already available, it does not allocate a new array. That is the whole point of pre-allocating a slice with capacity greater than its length.

x := make([]int, 0, 5)

Yields a slice [] over an array [0, 0, 0, 0, 0].

y := append(x, 20)

Yields a slice [20] over the same array, now [20, 0, 0, 0, 0].

fmt.Println(x, y, x[:2], y[:2])

Produces four slices:

x = [] // (its length & cap haven't changed)
y = [20] // (see append explanation above)
x[:2] = [20, 0] // (first two elements of the underlying array)
y[:2] = [20, 0] // (same two elements of the same array)

This is covered in detail in the Tour of Go and in further detail on the Go blog.

huangapple
  • 本文由 发表于 2022年1月26日 03:09:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/70854335.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定