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

查看:21
本文介绍了为什么我不能附加到一个切片,它是 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(), "
")

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

  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天全站免登陆