附加到 Go 结构中的切片属性
尝试将值附加到 Go 结构中的切片属性时,您可能会遇到意外行为如果未遵循特定的调用顺序。本文探讨了此问题背后的原因并提供了解决方案。
在提供的代码示例中,在不同的结构类型中定义了三个方法来演示该问题。 Test1 和 Test2 按预期工作,因为它们的 run() 方法直接对切片属性进行操作。但是,在 Test3 中,使用值接收器而不是指针接收器从 run() 调用组合()方法。
为什么需要指针接收器
在 Go 中,所有值都是按值传递,这意味着在调用函数或方法时会创建传递值的副本。在 Test3 的情况下,调用combo() 时会创建 Test3 值的副本,并且对该副本中的 slice 属性的修改不会反映在原始 Test3 结构中。
通过使用指针接收器,如func(c *Test3)combo(),直接修改原来的Test3结构体,消除了copy-local的问题
解决方案
解决方案是将combo()方法的接收者类型更改为指针接收者。这确保原始 Test3 结构体被该方法修改。
更新的代码
package main import ( "fmt" ) 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 } 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) } } 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: [0 1]
以上是为什么我需要一个指针接收器来附加到 Go 结构中的切片?的详细内容。更多信息请关注PHP中文网其他相关文章!