【发布时间】:2018-01-02 10:06:41
【问题描述】:
我正在尝试了解通道和 goroutine,并尝试编写一个 goroutine 来向服务器发出并发 API 请求
但是,当我使用 goroutine 运行代码时,它所花费的时间似乎与不使用 goroutine 的时间相同。
func sendUser(user string, ch chan<- string) {
resp,err := http.get("URL"/user)
//do the processing and get resp=string
ch <- resp
}
func AsyncHTTP(users []string) ([]string, error) {
ch := make(chan string)
var responses []string
var user string
for _ , user = range users {
go sendUser(user, ch)
for {
select {
case r := <-ch:
if r.err != nil {
fmt.Println(r.err)
}
responses = append(responses, r)
**//Is there a better way to show that the processing of response is complete**?
if len(responses) == len(users) {
return responses, nil
}
case <-time.After(50 * time.Millisecond):
fmt.Printf(".")
}
}
}
return responses, nil
}
问题:
即使我使用了 goroutine,请求完成时间与没有 goroutine 时一样吗?我在 goroutines 上做错了什么吗?
-
为了告诉工作不要再在这里等待,我正在使用:
if len(responses) == len(users)有没有更好的方法来表明响应的处理已经完成并告诉 ch 不要再等待了?
什么是wait.Syncgroup?如何在我的 goroutine 中使用它?
【问题讨论】:
-
您正在使用无缓冲通道。用
make(chan string, 10)或任何你想缓冲的数量来制作你的chan。 -
其实这不是问题。在您的循环中,您正在调用
go sendUser,但随后立即在循环中等待它。for先循环所有的go sendUser调用,然后再循环那里的其余逻辑。 -
@RayfenWindspear 但这不会导致死锁,因为通道只有 1 个缓冲区,如果我将“select”语句放在循环之外,那么一个缓冲区将如何保存来自的所有响应请求?
-
这就是它的美妙之处,频道不需要持有任何东西。一个无缓冲的通道基本上什么都没有,它直接将它传递给等待接收它的例程。您不在乎是否所有 100 或 1000 个 goroutine 都阻塞了
ch <- resp。他们已经完成了花费最多时间的 io 部分(http.get)。现在您可以一次使用一个响应。或者,如果需要,您可以使用更多 goroutine 来更快地使用响应。 -
@RayfenWindspear“或者如果你愿意,你可以使用更多的 goroutine 来更快地使用响应”。你能再解释一下吗?我怎样才能实现它?有没有更好的方法而不是 if len(responses) == len(users)
标签: go concurrency channel goroutine