为了账号安全,请及时绑定邮箱和手机立即绑定

Golang 将项目附加到切片

Golang 将项目附加到切片

Go
MMMHUHU 2021-07-09 14:02:26
为什么切片a保持不变?是否append()生成新切片?package mainimport (    "fmt")var a = make([]int, 7, 8)func Test(slice []int) {    slice = append(slice, 100)    fmt.Println(slice)}func main() {    for i := 0; i < 7; i++ {        a[i] = i    }    Test(a)    fmt.Println(a)}输出:[0 1 2 3 4 5 6 100][0 1 2 3 4 5 6]
查看完整描述

3 回答

?
Helenr

TA贡献1780条经验 获得超4个赞

在您的示例slice中,Test函数的参数接收调用者作用域中变量的副本a

由于切片变量包含一个仅引用底层数组的“切片描述符” ,因此在您的Test函数中,您可以slice连续多次修改保存在变量中的切片描述符,但这不会影响调用者及其a变量。

在Test函数外部,分配了一个长度为 7 和容量为 8 的切片,并填充了它的 7 个元素。

在Test函数内部,第一个append看到切片的容量仍然比它的长度大一个元素——换句话说,还有一个空间可以添加一个元素而无需重新分配。所以它“吃掉”剩余的元素并将其放置100到它上面,然后它调整切片描述符副本中的长度,使其等于切片的容量。这不会影响调用者范围内的切片描述符。


这就是你正在观察的。从 退出时Test,slice变量超出范围,切片引用的(新)底层数组也超出范围。


如果你想让Test行为像append,你必须从中返回新的切片——就像 doappend一样——并要求 的调用者以Test与使用相同的方式使用它append:


func Test(slice []int) []int {

    slice = append(slice, 100)


    fmt.Println(slice)


    return slice

}


a = Test(a)


查看完整回答
反对 回复 2021-07-12
?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

典型append用法是


a = append(a, x)

因为append可以就地修改其参数或返回其参数的副本以及附加条目,具体取决于其输入的大小和容量。使用先前附加到的切片可能会产生意想不到的结果,例如


a := []int{1,2,3}

a = append(a, 4)

fmt.Println(a)

append(a[:3], 5)

fmt.Println(a)

可以打印


[1 2 3 4]

[1 2 3 5]



查看完整回答
反对 回复 2021-07-12
?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

为了使您的代码工作而不必从 Test 返回切片,您可以传递这样的指针:


package main


import (

    "fmt"

)


var a = make([]int, 7, 8)


func Test(slice *[]int) {

    *slice = append(*slice, 100)


    fmt.Println(*slice)

}


func main() {


    for i := 0; i < 7; i++ {

        a[i] = i

    }


    Test(&a)


    fmt.Println(a)

}


查看完整回答
反对 回复 2021-07-12
  • 3 回答
  • 0 关注
  • 234 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信