请教一个问题 我用 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 ?
第二种和第三种的区别在哪呢?为什么时间会差这么多?
更多评论
我按照第一种请求的话,出现 panic 是 `no free connections available to host`,可能是因为我用的是 fasthttp。
我换成 go 的 http 就可以了,但是有一事不解,我用第一种方法写,相当于我同时开了 8000 多个协程,我感觉可能会崩掉(因为只是在我本地使用)。怎么能方便地去控制开协程的个数呢?比如我一次只想开 100 个协程。直接 chan 缓存成 100 就行了么?
望解答
#2
法1的panic,估计是在于你的http服务端处理不了一瞬间来的上万个请求,原因在于abc.com这个网站的请求处理能力,跟你的代码关系不大,代码应该是没问题的,法二与法三的区别在于,法二相当于总共开了2个携程再跑,法三相当于开了len(gidlist)个携程再跑,但是法三若想真正意义上开了len(gidlist)个携程去跑,必须保证下面的代码,len(list)==0,只有这样才会造成你看到的时间差,如果len(list) !=0,实际上法二与法三的执行时间是差不多的
if len(list) == 0 {
ch <- reqBody[0].Gid
}
ch <- ""
#3