go - 为什么我不能 append 到作为 golang 结构属性的 slice ?

标签 go struct append slice

我正在尝试将一个值 append 到 golang slice ,如果在第一个方法中调用该代码,则代码有效,但如果此方法调用另一个方法,代码似乎会失败。

示例(Test3 是我最初尝试做的):

package main

import (
  "fmt"
)

// This works

type Test1 struct {
  all []int
}

func (c Test1) run() []int {
  for i := 0; i < 2; i++ {
    c.all = append(c.all, i)
  }
  return c.all
}

// This works

var gloabl_all []int

type Test2 struct {}

func (c Test2) run() []int {
  c.combo()
  return gloabl_all
}

func (c Test2) combo() {
  for i := 0; i < 2; i++ {
    gloabl_all = append(gloabl_all, i)
  }
}

// This doesn't

type Test3 struct {
  all []int
}

func (c Test3) run() []int {
  c.combo()
  return c.all
}

func (c Test3) combo() {
  for i := 0; i < 2; i++ {
    c.all = append(c.all, i)
    fmt.Println("Test3 step", i + 1, c.all)
  }
}

func main() {
  test1 := &Test1{}
  fmt.Println("Test1 final:", test1.run(), "\n")

  test2 := &Test2{}
  fmt.Println("Test2 final:", test2.run(), "\n")

  test3 := &Test3{}
  fmt.Println("Test3 final:", test3.run())
}

这个输出:

Test1 final: [0 1] 

Test2 final: [0 1] 

Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: []

Playground 文案:https://play.golang.org/p/upEXINUvNu

如有任何帮助,我们将不胜感激!

最佳答案

Go 中的一切都是按值传递的。并且复制了传递的值。

Test3.combo() 有值(非指针)接收者:

func (c Test3) run() []int {
  c.combo()
  return c.all
}

func (c Test3) combo() {
  for i := 0; i < 2; i++ {
    c.all = append(c.all, i)
    fmt.Println("Test3 step", i + 1, c.all)
  }
}

这意味着当 Test3.combo()c.combo() 一样从 Test3.run() 调用时,副本是由 c(类型为 Test3)组成。 combo() 方法对副本进行操作。它正确地将 2 个数字 append 到 Test3.all,但是当此方法返回时,副本将被丢弃。

所以当 Test3.run() 返回 c.all 时,它返回一个空的 (nil) slice ,因为 slice 到Test3.combo() appended,是副本的字段,已被丢弃。

解决方案:简单地使用指针接收器:

func (c *Test3) combo() {
  for i := 0; i < 2; i++ {
    c.all = append(c.all, i)
    fmt.Println("Test3 step", i + 1, c.all)
  }
}

输出(在 Go Playground 上尝试):

Test1 final: [0 1] 

Test2 final: [0 1] 

Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: [0 1]

注意接收器中的星号*:func (c *Test3) combo()。通过添加它,您使接收者成为一个指针,因此当 combo() 被调用时,它只接收一个指向 Test3 类型值的指针,并且它会修改指向的值,Test3.run() 具有的值,因此当 combo() 返回时,更改不会丢失。

关于go - 为什么我不能 append 到作为 golang 结构属性的 slice ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42274235/

相关文章:

c - 使用 "\n"打印二维结构数组时出现问题

c - 结构体指针中的 "dereferencing pointer to incomplete type”

python - 将字母 append 到python列表中每个字符串的末尾

struct - 附加到结构 slice 时无效的内存地址或零指针取消引用

algorithm - 如何对 trie 表中的 IP 地址进行排序?

json - 在 Golang 中解析 JSON 数据

jQuery 多次追加对象

Golang - 为什么字符串 slice 元素不包含在 exec cat 中,除非我对它进行排序

json - 编码为 JSON 时,Golang 错误类型为空

python - 意外列表追加