在go例程运行时,如何将值分配给struct



我在项目中使用goroutines,我想将值分配给结构字段,但我不知道如何将通过使用mongodb quires获得的值分配给我正在显示的结构和查询的结构字段。

type AppLoadNew struct{
StripeTestKey      string                   `json:"stripe_test_key" bson:"stripe_test_key,omitempty"`
Locations          []Locations              `json:"location" bson:"location,omitempty"`
}
type Locations struct{
Id int `json:"_id" bson:"_id"`
Location  string `json:"location" bson:"location"`
}
func GoRoutine(){
values := AppLoadNew{}
go func() {
data, err := GetStripeTestKey(bson.M{"is_default": true})
if err == nil {
values.StripeTestKey := data.TestStripePublishKey
}
}()
go func() {
location, err := GetFormLocation(bson.M{"is_default": true})
if err == nil {
values.Locations := location
}
}()
fmt.Println(values) // Here it will nothing
// empty
}

你能帮我把所有的值都分配给AppLoadNew结构吗。

在Go中,没有任何值可以安全地用于并发读写(来自多个goroutine)。您必须同步访问。

从多个goroutine读取和写入变量可以使用sync.Mutexsync.RWMutex进行保护,但在您的情况下,还涉及其他一些内容:您应该等待2个启动的goroutine完成。为此,首选解决方案是sync.WaitGroup

由于这两个goroutine写入结构的两个不同字段(充当两个不同的变量),它们不必相互同步(请参阅此处的更多内容:我可以同时写入不同的切片元素吗)。这意味着使用sync.WaitGroup就足够了。

这就是如何使其安全和正确:

func GoRoutine() {
values := AppLoadNew{}
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
data, err := GetStripeTestKey(bson.M{"is_default": true})
if err == nil {
values.StripeTestKey = data.StripeTestKey
}
}()
wg.Add(1)
go func() {
defer wg.Done()
location, err := GetFormLocation(bson.M{"is_default": true})
if err == nil {
values.Locations = location
}
}()
wg.Wait()
fmt.Println(values)
}

请参见Go Playground上的一个(稍作修改)工作示例。

参见相关/类似问题:

从不同线程读取值

golang结构体在没有Lock的情况下并发读写也在运行,可以吗?

如何使可变线程安全

您可以将sync包与WaitGroup一起使用,下面是一个示例:

package main
import (
"fmt"
"sync"
"time"
)
type Foo struct {
One string
Two string
}
func main() {
f := Foo{}
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
// Perform long calculations
<-time.After(time.Second * 1)
f.One = "foo"
}()
wg.Add(1)
go func() {
defer wg.Done()
// Perform long calculations
<-time.After(time.Second * 2)
f.Two = "bar"
}()
fmt.Printf("Before %+vn", f)
wg.Wait()
fmt.Printf("After %+vn", f)
}

输出:

Before {One: Two:}
After {One:foo Two:bar}

最新更新