为什么我不能附加到作为 golang 结构属性的切片? [英] Why can't I append to a slice that's the property of a struct in golang?

查看:22
本文介绍了为什么我不能附加到作为 golang 结构属性的切片?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向 golang 切片附加一个值,如果在第一个方法中调用该代码,则该代码有效,但是如果该方法调用另一个方法,该代码似乎会失败.

I'm trying to append a value to a golang slice, the code works if it's called in the first method, but if this method calls another method, the code seems to fail.

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

Examples (Test3 is what I was originally trying to do):

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 中的一切都是按值传递的.并复制一个传递的值.

Everything in Go is passed by value. And a copy is made of the passed value.

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

Test3.combo() has value (non-pointer) receiver:

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,但是当此方法返回时,副本将被丢弃.

This means when Test3.combo() is called from Test3.run() like c.combo(), a copy is made of c (which is of type Test3). The combo() method operates on a copy. It properly appends 2 numbers to Test3.all, but when this method returns, the copy is discarded.

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

So when Test3.run() returns c.all, it returns an empty (nil) slice, because the slice to which Test3.combo() appended, was a field of a copy, and which has been discarded.

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

Solution: simply use a pointer receiver:

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 上试试):

Output (try it on the 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() 返回时,更改不会丢失.

Note the star * in the receiver: func (c *Test3) combo(). By adding it, you make the receiver a pointer, and so when combo() is called, it only receives a pointer to a value of type Test3, and it will modify the pointed value, the value that Test3.run() has, so when combo() returns, the changes are not lost.

这篇关于为什么我不能附加到作为 golang 结构属性的切片?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆