package main
import (
"fmt"
"net/http"
)
/*有 N 个任务,每个任务都会返回结果或者 error,通过固定的并发数(M)去执行。
如果其中有一个任务返回 error 时立即结束,否则全部执行完成时返回结果列表*/
func main() {
n := 10
m := 5
result := make([]string, n)
limitCh := make(chan interface{}, m)
errCh := make(chan error)
doneCh := make(chan interface{},1)
defer func() {
close(limitCh)
close(errCh)
}()
for state, i := true, 0; i < n; i++ {
state = true
for state {
select {
case limitCh <- nil:
fmt.Printf("开始第%d 个任务\n", i)
go func(i int) {
var err error
defer func() {
if i == n-1 {
close(doneCh)
}
if err != nil {
errCh <- err
}
<-limitCh
}()
ret, err := doTask()
if err != nil {
return
}
result[i] = ret
}(i)
state = false
case <-errCh:
return
default:
}
}
}
<- doneCh
fmt.Println(result)
}
func doTask() (string, error) {
// 模拟执行任务
resp, err := http.Get("
https://www.baidu.com")
if err != nil {
return "", err
}
defer resp.Body.Close()
return resp.Status, nil
}