使用指向外部结构的指针时如何使结构在其 Go 例程之外存活

How to make struct survive outside its Go routine when using pointers to external struct

当我 运行 此代码与 go run main.go 时,我看到此输出:

inner: {Bar:{Baz:xyz} BarPtr:0xc0000101e0}
outer: {Bar:{Baz:} BarPtr:<nil>}

我不明白为什么在将指针传递给例程时,例程中 created 的结构无法通过指针暴露在外部。

我知道我可以使用通道来发布在 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)
}

通过指针strct设置foo值的正确表达式是:

*strct = ownFoo

另一方面,表达式

strct = &ownFoo

strct 指针设置为 ownFoo 的地址并保持 foo 值不变。


请记住,如果您有一个从多个 goroutine 访问的变量,并且其中至少有一个是 writing/modifying 变量,如果没有适当的同步,您的代码必然会发生数据竞争,不管变量是直接访问还是通过本地指针访问,或者你有什么。