Golang中的输出是什么

Golang中的输出是什么 大家好,

我正在尝试理解下面的代码片段。 当我追踪输出时,逻辑上的输出与实际Go编译器的输出不同。 能否请您解释一下为什么Go编译器会给出不同的输出?

下面代码的输出会是什么,并请解释原因。

a := []int{0, 1, 2, 3}
x := a[:1]          //0
y := a[2:]          //2,3
x = append(x, y...) //0,2,3
x = append(x, y...) //0,2,3,2,3
fmt.Println(a, x)   //0,1,2,3,    0,2,3,2,3
}
// 实际输出 => [0 2 3 3] [0 2 3 3 3]

更多关于Golang中的输出是什么的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

你能具体说明是什么导致了困难吗?因为目前一切看起来都应该是正常的。

更多关于Golang中的输出是什么的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢您的回复。

在上面的示例中,append 操作具体发生了什么,它是如何改变值的?

能否请您详细阐述一下上面给出的示例。

请查看 Go切片:使用与内部原理

这里切片 x 有一个指向数组 a 位置 0 的指针,长度为 1。 将 y 追加到 x 会从位置 1 开始覆盖底层数组 a

并且,由于 ya 在位置 2 的一个切片,它也会看到这些更改。

只需在追加后打印 ay

请注意切片和数组。如果你向 y 追加的内容超出了 a 的容量,它会分配新的内存,并且不会改变 a

修改切片的元素会同时修改其底层数组的对应元素
例如,请参阅切片类似于数组的引用

在这里,第一次 appenda 更改为 [0, 2, 3, 3],因此 y 变为 [3,3]

这段代码的输出确实容易让人困惑,关键在于理解切片底层数组的共享机制。让我详细解释:

package main

import "fmt"

func main() {
    a := []int{0, 1, 2, 3}
    x := a[:1]          // x指向a的底层数组,长度为1,容量为4
    y := a[2:]          // y指向a的底层数组,从索引2开始
    
    // 第一次append:x容量足够,直接修改底层数组
    x = append(x, y...) // 将y的元素(2,3)追加到x
    // 此时底层数组变为:[0, 2, 3, 3]
    // a看到的是整个数组:[0, 2, 3, 3]
    // x看到的是[0:3]:[0, 2, 3]
    
    // 第二次append:x容量仍然足够(容量4,长度3)
    x = append(x, y...) // 再次追加y的元素
    // 此时y仍然指向底层数组索引2的位置
    // 但经过第一次append后,y指向的值已经是[3, 3]
    // 所以追加的是[3, 3]而不是[2, 3]
    
    fmt.Println(a, x) // 输出:[0 2 3 3] [0 2 3 3 3]
}

关键点解释:

  1. 切片共享底层数组xy都是a的切片,它们共享同一个底层数组。

  2. 第一次append的影响

    • x = append(x, y...)[2, 3] 追加到 x
    • 由于x的容量足够(容量4,当前长度1),直接在原数组上修改
    • 底层数组变为:[0, 2, 3, 3]
    • a现在看到的是 [0, 2, 3, 3]
    • y仍然指向索引2的位置,但该位置的值现在是3
  3. 第二次append的意外结果

    • 此时y指向的是底层数组索引2的位置,值为[3, 3]
    • 所以append(x, y...)实际上是追加[3, 3]而不是[2, 3]

可以通过以下代码验证中间状态:

package main

import "fmt"

func main() {
    a := []int{0, 1, 2, 3}
    fmt.Printf("初始状态: a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
    
    x := a[:1]
    fmt.Printf("x = a[:1]: x=%v, len=%d, cap=%d\n", x, len(x), cap(x))
    
    y := a[2:]
    fmt.Printf("y = a[2:]: y=%v, len=%d, cap=%d\n", y, len(y), cap(y))
    
    x = append(x, y...)
    fmt.Printf("第一次append后: a=%v, x=%v, y=%v\n", a, x, y)
    
    x = append(x, y...)
    fmt.Printf("最终结果: a=%v, x=%v\n", a, x)
}

输出:

初始状态: a=[0 1 2 3], len=4, cap=4
x = a[:1]: x=[0], len=1, cap=4
y = a[2:]: y=[2 3], len=2, cap=2
第一次append后: a=[0 2 3 3], x=[0 2 3], y=[3 3]
最终结果: a=[0 2 3 3], x=[0 2 3 3 3]

这就是为什么实际输出是 [0 2 3 3] [0 2 3 3 3] 而不是预期的 [0 1 2 3] [0 2 3 2 3]

回到顶部