【问题标题】:Refactor code to use a single channel in an idiomatic way重构代码以惯用的方式使用单个通道
【发布时间】:2021-02-26 11:53:36
【问题描述】:

我有以下代码:

package main

import (
    "fmt"
    "time"
)

type Response struct {
    Data   string
    Status int
}

func main() {
    var rc [10]chan Response
    for i := 0; i < 10; i++ {
        rc[i] = make(chan Response)
    }
    var responses []Response

    for i := 0; i < 10; i++ {
        go func(c chan<- Response, n int) {
            c <- GetData(n)
            close(c)
        }(rc[i], i)
    }

    for _, resp := range rc {
        responses = append(responses, <-resp)
    }

    for _, item := range responses {
        fmt.Printf("%+v\n", item)
    }
}

func GetData(n int) Response {
    time.Sleep(time.Second * 5)
    return Response{
        Data:   "adfdafcssdf4343t43gf3jn4jknon239nwcwuincs",
        Status: n,
    }
}

你能告诉我哪种方法是实现相同目标但使用单一渠道的正确方法吗?

【问题讨论】:

  • 你的目标是什么?启动多个 goroutine 并同步这些 goroutine 的结果?
  • 如果你想将数组或通道更改为单通道,请尝试使用大小为 10 的缓冲通道

标签: arrays go concurrency slice channel


【解决方案1】:

由于您可以同时编写不同的数组和切片元素,因此您不需要任何通道。详情请见Can I concurrently write different slice elements

只需启动您的 goroutine,并让它们写入适当的数组(或切片)元素。使用sync.WaitGroup 等待全部完成:

wg := &sync.WaitGroup{}
var responses [10]Response
for i := range responses {
    wg.Add(1)
    go func(n int) {
        defer wg.Done()
        responses[n] = GetData(n)
    }(i)
}

wg.Wait()
for _, item := range responses {
    fmt.Printf("%+v\n", item)
}

这输出与您的代码相同。在Go Playground 上试试吧。

另见相关:How to collect values from N goroutines executed in a specific order?

【讨论】:

  • 感谢您的回答。
猜你喜欢
  • 2015-05-12
  • 2021-01-29
  • 2015-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-12
  • 1970-01-01
相关资源
最近更新 更多