代码之家  ›  专栏  ›  技术社区  ›  kentor

将多个go例程的响应获取到一个数组中

  •  0
  • kentor  · 技术社区  · 7 年前

    密码

    func main() {
      log.Info("Collecting ints")
      var results []int32
      for _, broker := range e.BrokersByBrokerID {
          wg.Add(1)
          go getInt32(&wg)
      }
      wg.Wait()
      log.info("Collected")
    }
    
    func getInt32(wg *sync.WaitGroup) (int32, error) {
      defer wg.Done()
    
      // Just to show that this method may just return an error and no int32
      err := broker.Open(config)
      if err != nil && err != sarama.ErrAlreadyConnected {
        return 0, fmt.Errorf("Cannot connect to broker '%v': %s", broker.ID(), err)
      }
      defer broker.Close()
    
      return 1003, nil
    }
    

    我的问题

    2 回复  |  直到 7 年前
        1
  •  8
  •   icza    7 年前

    如果不处理作为goroutine启动的函数的返回值,它们将被丢弃。看见 What happens to return value from goroutine .

    您可以使用一个切片来收集结果,其中每个goroutine可以接收将结果放入的索引,或者接收元素的地址。看见 Can I concurrently write different slice elements . 请注意,如果使用此选项,则必须预先分配切片,并且只能写入属于goroutine的元素,不能“触摸”其他元素,也不能附加到切片。

    或者您可以使用一个通道,goroutine在该通道上发送包含其处理的项的索引或ID的值,以便收集goroutine可以识别或排序它们。看见 How to collect values from N goroutines executed in a specific order?

    Close multiple goroutine if an error occurs in one in go

    下面是一个使用频道时的示例。请注意,此处不需要waitgroup,因为我们知道,我们希望通道上的值与我们启动的goroutine数量相同。

    type result struct {
        task int32
        data int32
        err  error
    }
    
    func main() {
        tasks := []int32{1, 2, 3, 4}
    
        ch := make(chan result)
    
        for _, task := range tasks {
            go calcTask(task, ch)
        }
    
        // Collect results:
        results := make([]result, len(tasks))
    
        for i := range results {
            results[i] = <-ch
        }
    
        fmt.Printf("Results: %+v\n", results)
    }
    
    func calcTask(task int32, ch chan<- result) {
        if task > 2 {
            // Simulate failure
            ch <- result{task: task, err: fmt.Errorf("task %v failed", task)}
            return
        }
    
        // Simulate success
        ch <- result{task: task, data: task * 2, err: nil}
    }
    

    输出(在屏幕上尝试ot) Go Playground

    Results: [{task:4 data:0 err:0x40e130} {task:1 data:2 err:<nil>} {task:2 data:4 err:<nil>} {task:3 data:0 err:0x40e138}]
    
        2
  •  4
  •   cn007b Dheerendra Kulkarni    7 年前

    package main
    
    import (
        "fmt"
        "log"
        "sync"
    )
    
    var (
        BrokersByBrokerID = []int32{1, 2, 3}
    )
    
    type result struct {
        data string
        err string // you must use error type here
    }
    
    func main()  {
        var wg sync.WaitGroup
        var results []result
        ch := make(chan result)
    
        for _, broker := range BrokersByBrokerID {
            wg.Add(1)
            go getInt32(ch, &wg, broker)
        }
    
        go func() {
            for v := range ch {
                results = append(results, v)
            }
        }()
    
        wg.Wait()
        close(ch)
    
        log.Printf("collected %v", results)
    }
    
    func getInt32(ch chan result, wg *sync.WaitGroup, broker int32) {
        defer wg.Done()
    
        if broker == 1 {
            ch <- result{err: fmt.Sprintf("error: gor broker 1")}
            return
        }
    
        ch <- result{data: fmt.Sprintf("broker %d - ok", broker)}
    }
    

    结果如下所示:

    2019/02/05 15:26:28 collected [{broker 3 - ok } {broker 2 - ok } { error: gor broker 1}]