【问题标题】:Why can't I append to a slice that's the property of a struct in golang?为什么我不能附加到 golang 中结构属性的切片?
【发布时间】:2017-10-18 04:48:54
【问题描述】:

我正在尝试将值附加到 golang 切片,如果在第一个方法中调用代码可以工作,但如果此方法调用另一个方法,代码似乎会失败。

示例(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: []

游乐场文案:https://play.golang.org/p/upEXINUvNu

任何帮助将不胜感激!

【问题讨论】:

  • 必须使用指针接收器,否则您将附加到副本。

标签: go struct append slice


【解决方案1】:

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 个数字附加到 Test3.all,但是当此方法返回时,副本被丢弃。

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

解决方案:只需使用指针接收器:

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() 返回时,更改不会丢失。

【讨论】:

猜你喜欢
  • 2016-12-24
  • 1970-01-01
  • 2015-11-22
  • 2021-10-23
  • 2016-05-25
  • 2019-01-02
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
相关资源
最近更新 更多