Go 并发控制利器 ants 使用文档
https://github.com/panjf2000/ants
1.1 什么是 ants
ants
是一个高性能的 Go 语言 goroutine 池,它能复用已完成任务的 goroutine,避免频繁创建和销毁 goroutine,节省 CPU 与内存开销,并且能限制并发数量防止资源被耗尽。
1.2 安装
go get -u github.com/panjf2000/ants/v2
1.3 最简单的例子
package mainimport ("fmt""time""github.com/panjf2000/ants/v2"
)func main() {// 创建一个容量为 10 的 goroutine 池pool, _ := ants.NewPool(10)defer pool.Release() // 程序结束释放资源// 提交任务for i := 0; i < 20; i++ {n := i_ = pool.Submit(func() {fmt.Printf("Task %d running\n", n)time.Sleep(time.Second)})}fmt.Println("All tasks submitted")time.Sleep(3 * time.Second) // 等待任务执行完
}
特点:
- 同时最多只有 10 个任务运行。
- 其余任务排队等待空闲 worker。
2. 进阶篇
2.1 核心 API
方法 | 作用 |
---|---|
ants.NewPool(size, options...) | 创建一个普通任务池 |
ants.NewPoolWithFunc(size, func, options...) | 创建一个绑定任务处理函数的池 |
Submit(task) | 提交任务到池 |
Invoke(param) | 提交参数,调用绑定函数 |
Running() | 当前正在运行的 worker 数量 |
Free() | 当前空闲 worker 数量 |
Cap() | 池容量 |
Tune(size) | 动态调整容量 |
Release() | 释放所有资源 |
Reboot() | 重启一个已释放的池 |
2.2 常用配置项
ants.WithPreAlloc(true) // 预先分配内存,减少运行时分配
ants.WithNonblocking(true) // worker 不够时立即返回错误,而不是等待
ants.WithMaxBlockingTasks(1000) // 最大等待任务数
ants.WithPanicHandler(func(err interface{}) {fmt.Println("panic:", err) // 捕获任务中的 panic
})
ants.WithExpiryDuration(time.Second * 10) // 空闲 worker 过期时间
2.3 PoolWithFunc
用法
package mainimport ("fmt""github.com/panjf2000/ants/v2""time"
)func main() {// 定义处理函数handler := func(data interface{}) {fmt.Printf("Processing: %v\n", data)time.Sleep(time.Millisecond * 500)}// 创建绑定函数的池pool, _ := ants.NewPoolWithFunc(5, handler)defer pool.Release()for i := 0; i < 10; i++ {_ = pool.Invoke(i) // 直接传参数}
}
3. 实战篇
3.1 批量任务执行
场景:你需要批量处理 10000 条数据,但不希望一次性开 10000 个 goroutine。
package mainimport ("fmt""sync""time""github.com/panjf2000/ants/v2"
)func processTask(id int) {fmt.Printf("Task %d start\n", id)time.Sleep(time.Second)fmt.Printf("Task %d done\n", id)
}func main() {var wg sync.WaitGrouppool, _ := ants.NewPool(50) // 控制并发为 50defer pool.Release()for i := 0; i < 10000; i++ {wg.Add(1)taskID := i_ = pool.Submit(func() {defer wg.Done()processTask(taskID)})}wg.Wait()
}
3.2 HTTP 并发控制
爬取多个 URL,但限制同时请求的数量。
package mainimport ("fmt""net/http""sync""github.com/panjf2000/ants/v2"
)func fetch(url string) {resp, err := http.Get(url)if err != nil {fmt.Println(err)return}defer resp.Body.Close()fmt.Println(url, resp.StatusCode)
}func main() {urls := []string{"https://golang.org","https://github.com","https://google.com",}var wg sync.WaitGrouppool, _ := ants.NewPool(5)defer pool.Release()for _, url := range urls {wg.Add(1)u := url_ = pool.Submit(func() {defer wg.Done()fetch(u)})}wg.Wait()
}
4. 最佳实践与注意事项
-
适合长时间运行的服务
- 在任务密集的服务中能显著降低内存占用。
-
任务不宜过大或阻塞太久
- 单个任务阻塞会占用 worker,影响吞吐量。
-
panic 处理必须配置
- 避免单个任务导致池崩溃。
-
选择合适的池大小
- 一般为
CPU核数 * N
,N 根据 IO 密集度调整。
- 一般为
-
性能对比
- 对于少量任务,直接开 goroutine 可能更快;
- 对于大规模并发,
ants
会明显减少 GC 压力。