【发布时间】:2020-02-14 01:51:36
【问题描述】:
我使用多个 goroutine 来运行任务,当其中一个完成时,返回并关闭通道,这将导致恐慌:在关闭的通道上发送。
见代码:
func fetch(urls []string) *http.Response {
ch := make(chan *http.Response)
defer close(ch)
for _, url := range urls {
go func() {
resp, err := http.Get(url)
if err == nil {
ch <- resp
}
}()
}
return <-ch
}
不关闭频道是没有问题的,但是我觉得不是很好,有什么优雅的解决方案吗?
感谢所有答案,这是我的最终代码:
func fetch(urls []string) *http.Response {
var wg sync.WaitGroup
ch := make(chan *http.Response)
wg.Add(len(urls))
for _, url := range urls {
go func(url string) {
defer wg.Done()
resp, err := http.Get(url)
if err == nil {
ch <- resp
}
}(url)
}
go func() {
wg.Wait()
close(ch)
}()
return <-ch
}
【问题讨论】:
-
问题是
fetch()在你的 goroutine 完成之前返回,当它返回时,defer close(ch)执行。你可能需要一个等待组。 -
return <-ch也没有意义......它只会返回一个值(任何 goroutine 返回的第一个值),但您正在获取多个值。我不确定你的目标是什么,但你的代码没有意义。 -
这可能是有道理的,假设您只想要第一个响应。不过我也觉得很奇怪,很可能应该返回频道。
-
@Clément:这方面可能是有道理的,但是你需要(优雅地)清理其他 goroutine,这还没有完成。
标签: go