Как назначить значения для структуры во время выполнения процедур go? - PullRequest
0 голосов
/ 31 января 2019

Я использую goroutines в своем проекте, и я хочу присвоить значения полям структуры, но я не знаю, как я буду назначать значения, полученные с помощью запросов mongodb, к полям структуры, которые я показываюstruct и query тоже.

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 голосов
/ 31 января 2019

Вы можете использовать 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}
0 голосов
/ 31 января 2019

В Go никакое значение не является безопасным для одновременного чтения и записи (из нескольких процедур).Вы должны синхронизировать доступ.

Чтение и запись переменных из нескольких групп могут быть защищены с помощью sync.Mutex или sync.RWMutex, но в вашем случае есть что-то ещевовлечено: вам следует дождаться завершения двух запущенных программ.Для этого, подходящее решение: sync.WaitGroup.

И так как 2 программы пишут 2 разных поля структуры (которые действуют как 2 различные переменные), они недолжны быть синхронизированы друг с другом (подробнее об этом здесь: Могу ли я одновременно написать разные элементы среза ).Это значит, что достаточно использовать 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Детская площадка .

См. Похожие / похожие вопросы:

Чтение значений из другого потока

одновременное чтение и запись в golang structбез блокировки тоже работает нормально?

Как сделать переменную поточно-безопасной

...