请教一个问题 我用 go 写了一个小脚本,批量请求快一万个请求,处理数据。用 goroutine 写了 3 种,得到的结果都不一样,不知道为什么,求教
> `FetchProductpage` 是一次 http 请求
> `gidsList` 是一个 []string,存放 id
```go
func FetchProductpage(ch chan<- string) {
req := &fasthttp.Request{}
req.SetRequestURI("http://abc.com")
req.Header.SetContentType("application/json")
req.Header.SetMethod("POST")
res := &fasthttp.Response{}
if err := fasthttp.Do(req, res); err != nil {
panic(reqBody[0].Gid + "handle error")
}
resBody := res.Body()
var list []int
json.Unmarshal(resBody, &list)
if len(list) == 0 {
ch <- reqBody[0].Gid
}
ch <- ""
}
```
```go
// 法一 直接 panic
ch := make(chan string)
defer close(ch)
for index, gid := range gidsList {
go func(index int, gid string) {
println("第 ", index, " 个商品:", gid)
FetchProductpage(ch)
}(index, gid)
}
for range gidsList {
noGid := <-ch
if noGid != "" {
noGidsLen++
}
}
println("其中 ", noGidsLen, " 个没有结果")
```
![1.png](https://static.studygolang.com/191117/fdd89b7985d7e3ae3e87afbddab11dbc.png)
```go
// 法二 用了 10 分钟
ch := make(chan string)
defer close(ch)
go func() {
for _, gid := range gidsList {
println("第 ", index, " 个商品:", gid)
FetchProductpage(ch)
}
}()
for range gidsList {
noGid := <-ch
if noGid != "" {
noGidsLen++
}
}
println("其中 ", noGidsLen, " 个没有结果")
```
```go
// 法三 只用了2分钟
ch := make(chan string)
defer close(ch)
for index, gid := range gidsList {
go func(index int, gid string) {
println("第 ", index, " 个商品:", gid)
FetchProductpage(ch)
}(index, gid)
noGid := <-ch
if noGid != "" {
noGidsLen++
f.WriteString(noGid + "\n")
}
}
println("其中 ", noGidsLen, " 个没有结果")
```
第一种写法为什么会 panic ?
第二种和第三种的区别在哪呢?为什么时间会差这么多?
新加一个blockChan,带缓存(数量100)
blockChan<-struct{}
写在
FetchProductpage(ch) 调用之前.
fetchProductpage 调用完之后 _=<-blockChan取出值
这样就可以限制请求数了.
#5
更多评论
我按照第一种请求的话,出现 panic 是 `no free connections available to host`,可能是因为我用的是 fasthttp。
我换成 go 的 http 就可以了,但是有一事不解,我用第一种方法写,相当于我同时开了 8000 多个协程,我感觉可能会崩掉(因为只是在我本地使用)。怎么能方便地去控制开协程的个数呢?比如我一次只想开 100 个协程。直接 chan 缓存成 100 就行了么?
望解答
#2