Go 并发控制利器 ants 使用方法与实践

 更新时间:2026年07月08日 09:28:59   作者:言之。  
ants是一个高效的Go语言goroutine池实现,通过复用已完成任务的goroutine来减少资源开销并限制并发数量,本文就来详细的介绍一下Go 并发控制利器 ants的使用,感兴趣的可以了解一下

1.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 main

import (
	"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.3PoolWithFunc用法

package main

import (
	"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 main

import (
	"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.WaitGroup
	pool, _ := ants.NewPool(50) // 控制并发为 50
	defer 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 main

import (
	"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.WaitGroup
	pool, _ := 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. 最佳实践与注意事项

  1. 适合长时间运行的服务

    • 在任务密集的服务中能显著降低内存占用。
  2. 任务不宜过大或阻塞太久

    • 单个任务阻塞会占用 worker,影响吞吐量。
  3. panic 处理必须配置

    • 避免单个任务导致池崩溃。
  4. 选择合适的池大小

    • 一般为 CPU核数 * N,N 根据 IO 密集度调整。
  5. 性能对比

    • 对于少量任务,直接开 goroutine 可能更快;
    • 对于大规模并发,ants 会明显减少 GC 压力。

到此这篇关于Go 并发控制利器 ants 使用文档的文章就介绍到这了,更多相关Go 并发控制利器 ants内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Go语言中的Slice链式操作

    详解Go语言中的Slice链式操作

    这篇文章主要为大家详细介绍了Go语言中的Slice链式操作的相关知识,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-04-04
  • Go语言中字符串赋值中的问题与解决方法

    Go语言中字符串赋值中的问题与解决方法

    这篇文章主要为大家详细介绍了Go语言中字符串赋值会出现的一些问题以及解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下
    2024-12-12
  • Golang中tinyrpc框架的源码解读详解

    Golang中tinyrpc框架的源码解读详解

    tinyrpc是一个高性能的基于protocol buffer的rpc框架。项目代码非常少,很适合初学者进行golang的学习。本文将从源码的角度带大家了解tinyrpc框架的使用,需要的可以参考一下
    2023-01-01
  • goland 实现自动格式化代码

    goland 实现自动格式化代码

    这篇文章主要介绍了goland 实现自动格式化代码的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go基础教程系列之import导入包(远程包)和变量初始化详解

    Go基础教程系列之import导入包(远程包)和变量初始化详解

    这篇文章主要介绍了Go基础教程系列之import导包和初始化详解,需要的朋友可以参考下
    2022-04-04
  • GoLang channel底层代码实现详解

    GoLang channel底层代码实现详解

    Channel和goroutine的结合是Go并发编程的大杀器。而Channel的实际应用也经常让人眼前一亮,通过与select,cancel,timer等结合,它能实现各种各样的功能。接下来,我们就要梳理一下GoLang channel底层代码实现
    2022-10-10
  • Go标准库之Requests的介绍与基本使用

    Go标准库之Requests的介绍与基本使用

    Python中的Requests库非常强大,所以Go开发者模仿Python的Requests库,由此诞生了Grequests库,本文主要介绍了Requests的基本使用,有需要的可以参考下
    2024-04-04
  • 15个Golang中时间处理的实用函数

    15个Golang中时间处理的实用函数

    在Go编程中,处理日期和时间是一项常见任务,涉及到精确性和灵活性,本文将介绍一系列实用函数,它们充当time包的包装器,需要的可以参考下
    2024-01-01
  • 浅谈GoLang几种读文件方式的比较

    浅谈GoLang几种读文件方式的比较

    这篇文章主要介绍了浅谈GoLang几种读文件方式的比较,一般来说常用的有三种。使用Read加上buffer,使用bufio库和ioutil 库,非常具有实用价值,需要的朋友可以参考下
    2019-01-01
  • Go基础教程系列之WaitGroup用法实例详解

    Go基础教程系列之WaitGroup用法实例详解

    这篇文章主要介绍了Go基础教程系列之WaitGroup用法实例详解,需要的朋友可以参考下
    2022-04-04

最新评论