【发布时间】:2019-10-18 14:00:20
【问题描述】:
当我使用go run main.go 运行此代码时,我会看到以下输出:
inner: {Bar:{Baz:xyz} BarPtr:0xc0000101e0}
outer: {Bar:{Baz:} BarPtr:<nil>}
我不明白为什么在将指针传递给例程时,在该例程中创建的结构 不能通过指针暴露在外部。
我知道我可以使用通道来发布在 Go 例程中创建的结构,但是我正在处理的这段代码需要太多额外的样板代码。如果可能,我想使用带有指针的等待组,但我找不到方法,所以我想知道这是否可能?
对我来说,我应该能够通过指针公开一个内部结构,但我不确定编译器是否会默默地忽略这一点,或者我无法理解 Go 的一些基本特性?
package main
import (
"fmt"
"sync"
)
type Foo struct {
Bar Bar
BarPtr *Bar
}
type Bar struct {
Baz string
}
func main() {
foo := Foo{}
var wg sync.WaitGroup
// the real example has more routines, so I need a wait group
wg.Add(1)
go func(strct *Foo) {
defer wg.Done()
bar1 := Bar{
Baz: "xyz",
}
bar2 := Bar{
Baz: "abc",
}
ownFoo := Foo{
Bar: bar1,
BarPtr: &bar2,
}
fmt.Printf("inner: %+v\n", ownFoo)
strct = &ownFoo
}(&foo)
wg.Wait()
fmt.Printf("outer: %+v\n", foo)
}
【问题讨论】:
-
struct 是一个最初指向 foo 的指针。让这个指针指向其他地方(这里指向 ownFoo)丝毫不会影响 foo,我不清楚为什么会期望它会这样做。
-
看来我可以使用带有等待组的全局变量,所以我知道 Go 例程是使用该全局变量完成的,我可以安全地访问它的值,或者我可以使用通道。我想使用指针来避免使用从 Go 例程内部引用的全局变量。
-
即使您尝试执行的指针操作会起作用,您仍然需要围绕指针分配进行同步。代码中的注释表明无论如何都需要一个WaitGroup,那为什么不直接修改foo呢?
-
foo可以从不同的包创建和注入。我试图尽量减少样板代码的数量(例如,不需要额外的“包装”结构和通道),但通过使用等待组和避免全局变量来保持某种安全/同步。 -
@TPPZ goroutine 与否,以更改您使用
*strct = ownFoo而不是strct = &ownFoo的指针指向的值。strct = &ownFoo改变的是指针,而不是指向的值。
标签: pointers go struct goroutine