在go例程运行时如何为struct赋值?

时间:2019-01-31 09:24:17

标签: go concurrency goroutine

我在项目中使用goroutines,我想将值分配给struct字段,但我不知道如何使用mongodb quire将值分配给struct字段,我将如何显示结构和查询。

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结构吗?

2 个答案:

答案 0 :(得分:2)

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

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

并且由于这两个goroutines编写了一个结构的2个不同字段(它们充当2个不同的变量),因此它们不必彼此同步(请参见此处的更多信息:Can I concurrently write different slice elements)。这意味着使用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上查看一个(稍作修改的)工作示例。

查看相关/类似问题:

Reading values from a different thread

golang struct concurrent read and write without Lock is also running ok?

How to make a variable thread-safe

答案 1 :(得分:1)

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

package main

import (
    "fmt"
    "sync"
    "time"
)

type Foo struct {
    One string
    Two string
}

func main() {
    f := Foo{}
    var wg sync.WaitGroup
    go func() {
        defer wg.Done()
        wg.Add(1)
        // Perform long calculations
        <-time.After(time.Second * 1)
        f.One = "foo"
    }()
    go func() {
        defer wg.Done()
        wg.Add(1)
        // Perform long calculations
        <-time.After(time.Second * 2)
        f.Two = "bar"

    }()

    fmt.Printf("Before %+v\n", f)
    wg.Wait()
    fmt.Printf("After %+v\n", f)
}

输出:

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