go: 结构体中的数组丢失了其内容

huangapple go评论81阅读模式
英文:

go: array in struct looses its content

问题

以下是给定的Go代码的翻译:

package main

import "fmt"

type orderPosition struct{
   art string
   qty string   
}

type order struct{
   posList []orderPosition
}

func main() {
  o := new(order)
  o.loadPos()
  fmt.Printf("# pos: %d\n",len(o.posList))
}

func (o order) loadPos() {
  o.posList = append(o.posList, orderPosition {art: "art 1", qty: "2 pc"})
  o.posList = append(o.posList, orderPosition {art: "art 2", qty: "7 pc"})
  fmt.Printf("# pos: %d\n",len(o.posList))
}

输出结果为:

# pos: 2
# pos: 0

方法loadPos用于填充订单中的位置。但是一旦方法执行完毕,位置列表的内容就会丢失。

为什么数组会丢失其内容?

非常感谢任何帮助!

英文:

The following go code (shared: link) should insert two positions in an order (both order and position are structs:

package main

import "fmt"

type orderPosition struct{
   art string
   qty string   
}

type order struct{
   posList []orderPosition
}

func main() {
  o := new(order)
  o.loadPos()
  fmt.Printf("# pos: %d\n",len(o.posList))

}

func (o order) loadPos() {
  o.posList = append(o.posList, orderPosition {art: "art 1", qty: "2 pc"})
  o.posList = append(o.posList, orderPosition {art: "art 2", qty: "7 pc"})
  fmt.Printf("# pos: %d\n",len(o.posList))
}

The output is:

# pos: 2
# pos: 0    

The method loadPos fills the positions in the order. But as soon as the method is left the list of positions is lost.

Why is the array loosing its content?

Any help would be greatly appreciated.

答案1

得分: 3

你的loadPos()方法使用的是值接收器(而不是指针),这意味着它在order对象的副本上操作。所以当你调用o.loadPos()时,Go语言会复制o,并在该副本上调用loadPos()

解决方案很简单,只需将接收器改为指针:

func (o *order) loadPos() {

https://play.golang.org/p/PATpBCZLT7

英文:

Your loadPos() method is using a value receiver (as opposed to a pointer), meaning that it's operating on a copy of the order object.
So when you call o.loadPos(), go is copying o, and calling loadPos() on that copy.

The solution is to simply change the receiver to a pointer:

func (o *order) loadPos() {

<sup>https://play.golang.org/p/PATpBCZLT7</sup>

答案2

得分: 2

扩展Patrick的回答,Golang FAQ中有更多的见解。

我应该在值上还是指针上定义方法?

func (s *MyStruct) pointerMethod() { } // 指针方法
func (s MyStruct) valueMethod()   { } // 值方法

首先,最重要的是,方法是否需要修改接收者?如果需要修改,接收者必须是指针。(切片和映射表现为引用,所以它们的情况稍微复杂一些,但是例如要在方法中更改切片的长度,接收者仍然必须是指针。)在上面的示例中,如果pointerMethod修改了s的字段,调用者将看到这些更改,但是valueMethod是使用调用者参数的副本调用的(这就是传递值的定义),所以它所做的更改对调用者是不可见的。

其次是效率的考虑。如果接收者很大,比如一个大的结构体,使用指针接收者会更便宜。

接下来是一致性。如果类型的某些方法必须具有指针接收者,那么其余的方法也应该具有指针接收者,这样方法集在使用类型的方式上是一致的。

对于基本类型、切片和小结构体等类型,值接收者非常便宜,所以除非方法的语义要求使用指针,否则值接收者是高效和清晰的。

英文:

Extending the Patrick answer, there is more insight in Golang FAQ

Should I define methods on values or pointers?

func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct)  valueMethod()   { } // method on value

> First, and most important, does the method need to modify the
> receiver? If it does, the receiver must be a pointer. (Slices and maps
> act as references, so their story is a little more subtle, but for
> instance to change the length of a slice in a method the receiver must
> still be a pointer.) In the examples above, if pointerMethod modifies
> the fields of s, the caller will see those changes, but valueMethod is
> called with a copy of the caller's argument (that's the definition of
> passing a value), so changes it makes will be invisible to the caller.
>
>
> Second is the consideration of efficiency. If the receiver is large, a
> big struct for instance, it will be much cheaper to use a pointer
> receiver.
>
> Next is consistency. If some of the methods of the type must have
> pointer receivers, the rest should too, so the method set is
> consistent regardless of how the type is used.

For types such as basic types, slices, and small structs, a value
receiver is very cheap so unless the semantics of the method requires
a pointer, a value receiver is efficient and clear.

huangapple
  • 本文由 发表于 2015年3月28日 16:06:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/29315014.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定