问题
I have the following code:
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,
}
}
Can you tell me which would be the right way to accomplish the same goal but using a single channel?
回答1:
Since you can write different array and slice elements concurrently, you don't need any channels in your case. For details, see Can I concurrently write different slice elements.
Just launch your goroutines, and have them write in the appropriate array (or slice) elements. Use a sync.WaitGroup to wait for all to complete:
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)
}
This outputs the same as your code. Try it on the Go Playground.
Also see related: How to collect values from N goroutines executed in a specific order?
来源:https://stackoverflow.com/questions/64838433/refactor-code-to-use-a-single-channel-in-an-idiomatic-way