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

附加到其他切片内的结构上的切片不持久

附加到其他切片内的结构上的切片不持久

Go
小唯快跑啊 2023-04-24 16:13:56
例如:package mainimport "fmt"type Test struct {  elems []string}func main() {  initial := Test{    elems: make([]string, 0),  }  initial.elems = append(initial.elems, "apple")  fmt.Println(initial.elems) // #1 [apple]  s := make([]Test, 0)  s = append(s, initial)  initial.elems = append(initial.elems, "bannana")  fmt.Println(initial.elems) // #2 [apple bannana]  fmt.Println(s[0].elems) // #3 [apple]  second := s[0]  second.elems = append(second.elems, "carrot")  fmt.Println(second.elems) // #4 [apple bannana]}我正在寻求帮助来理解打印语句 #3 和 #4。在#3 中我期待[apple bannana],在#4 中我期待[apple bannana carrot]。据我了解,elems作为切片的字段会自动通过引用传递,因此我在上面的代码块中所做的每个追加都应该修改底层数组。但是,显然并非如此。initial所以,我的问题是:当它被插入到一个使它不起作用的切片中时会发生什么?此外,如何编写此代码才能在 print 语句 #4 中获得预期结果?
查看完整描述

2 回答

?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

在 Golang 中提到:


映射和切片值的行为类似于指针:它们是包含指向底层映射或切片数据的指针的描述符。复制映射或切片值不会复制它指向的数据。


您附加到切片的方式s是通过将 Test 结构的副本添加到切片来创建一个新切片s。因此,您没有设置指向原始Test结构的指针。因此,如果结构内部的数据发生变化,它也会反映在切片中。这就是你面临的问题。


  initial.elems = append(initial.elems, "apple")

  fmt.Println(initial.elems) // #1 [apple]


  s := make([]Test, 0) // this should be pointer to the struct to have teh changes in future to original struct.

  s = append(s, initial) // appending to the s slice

Test在制作 slice 时创建一个指向结构的指针s,每当您更改原始结构中的元素时,它都会反映更改。例如:


package main

import "fmt"


type Test struct {

  elems []string

}


func main() {

  initial := Test{

    elems: make([]string, 0),

  }

  initial.elems = append(initial.elems, "apple")

  fmt.Println(initial.elems) // #1 [apple]


  s := make([]*Test, 0) // create a pointer to Test struct.

  s = append(s, &initial)


  initial.elems = append(initial.elems, "bannana")

  fmt.Println(initial.elems) // #2 [apple bannana]

  fmt.Printf("%+v\n",*s[0]) // #3 [apple banana]


  second := s[0]

  second.elems = append(second.elems, "carrot")

  fmt.Println(second.elems) // #4 [apple bannana carrot]

}

输出:-


[apple]

[apple bannana]

{elems:[apple bannana]}

[apple bannana carrot]

Go Playground上的工作代码



查看完整回答
反对 回复 2023-04-24
?
BIG阳

TA贡献1859条经验 获得超6个赞

这是由事实引起的,即initial变量与s[0]- 它们是两个自Test变量并且附加到一个不会改变第二个。initial传递给时按值复制到不同的对象append()

证明:

fmt.Printf("second: %p, initial: %p\n", &second.elems[0], &initial.elems[0])

(其中second.elems[0] == "apple"initial.elems[0] == "apple")输出

second: 0xc00000a120, initial: 0xc00000a0c0

这表明这是真的


查看完整回答
反对 回复 2023-04-24
  • 2 回答
  • 0 关注
  • 129 浏览
慕课专栏
更多

添加回答

举报

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