我有以下内容,并且正在尝试进行一些并发的http调用,以便加快整个程序的速度,而不是一个接一个地进行每个调用:
package main
import (
"fmt"
"net/http"
"time"
)
type U struct {
u string
name string
resp *http.Response
}
func main() {
urls := []*U{
&U{"example", "http://www.example.com", nil},
&U{"yahoo", "http://www.yahoo.com", nil},
&U{"google", "http://www.google.com", nil},
}
ch := make(chan *U)
// read from the channel
go func() {
for c := range ch {
for i, u := range urls {
if c.name == u.name {
urls[i] = c
}
}
}
}()
// fetch the stuff
for _, u := range urls {
go func(u *U) {
var err error
u, err = getResponse(u)
if err != nil {
fmt.Println(err)
}
ch <- u
}(u)
}
for i, u := range urls {
fmt.Println(i, u.resp) // all nil
}
}
func getResponse(u *U) (*U, error) {
c := &http.Client{
Timeout: 10 * time.Second,
}
var err error
u.resp, err = c.Get(u.u)
return u, err
}
https://play.golang.org/p/Zko8xkEqDMB
在打印时我似乎做得不好
0 <nil>
1 <nil>
2 <nil>
它也应该打印响应。
如何确保等到一切完成后才能前进?好。谢谢。
答案 0 :(得分:3)
您不是在等待响应返回。这等效于:
urls := []*U{
&U{"example", "http://www.example.com", nil},
&U{"yahoo", "http://www.yahoo.com", nil},
&U{"google", "http://www.google.com", nil},
}
for i, u := range urls {
fmt.Println(i, u.resp) // all nil
}
相反,您可以使用sync.WaitGroup
确保在显示响应之前完成所有工作:
var wg sync.WaitGroup
for _, u := range urls {
wg.Add(1) // Add job to the waitgroup
go func(u *U) {
var err error
u, err = getResponse(u)
if err != nil {
fmt.Println(err)
}
ch <- u
wg.Done() // Note when the job is done
}(u)
}
wg.Wait() // wait until all the Add'd jobs are Done'd
for i, u := range urls {
fmt.Println(i, u.resp) // all nil
}
或者您可以与getResponse
在同一链中处理打印响应:
for _, u := range urls {
go func(u *U) {
var err error
u, err = getResponse(u)
if err != nil {
fmt.Println(err)
}
printResponse(u) // implement printResponse however
ch <- u
}(u)
}