限制 Goroutine
控制并发量
限制 Goroutine 是 CoddyKit 上的免费 Go Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。
并发限流
有时您限制的不是每秒请求数,而是同时运行的 goroutine 数量。无论请求的时间安排如何,这都能限制资源所承受的同时负载。
- 限制并行度
- 保护连接池
- 防止内存峰值
信号量通道
带缓冲的通道可以充当计数信号量。它的容量等于最大并发数。获取许可时发送令牌,释放许可时接收令牌。
sem := make(chan struct{}, 3)获取与释放
开始工作前,请向通道发送数据以获取一个槽位(通道已满时会阻塞)。完成后,请接收数据来释放槽位,为另一个 goroutine 腾出空间。
sem <- struct{}{} // acquire
// do work
<-sem // release为什么使用 struct{}
空结构体 struct{}{} 占用零字节。将它用作通道元素后,信号量就只传递信号,不会浪费内存。
循环限流
为每个任务启动一个 goroutine,但让每个 goroutine 都受信号量控制。最多只有 cap 个 goroutine 会同时执行实际工作,其余 goroutine 会在获取许可处阻塞。
for _, task := range tasks {
sem <- struct{}{}
go func(t Task) {
defer func() { <-sem }()
process(t)
}(t)
}与 WaitGroup 配合
信号量可以限制并发数,但不会告诉您所有任务何时完成。请将它与 sync.WaitGroup 结合,以等待所有任务结束。
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
defer func() { <-sem }()
process(t)
}()在 defer 中释放
请始终在 defer 中释放槽位,这样即使工作发生恐慌或提前返回,槽位也能被释放。忘记释放会造成槽位泄漏,最终使新的获取者发生死锁。
完整的限流运行示例
此程序运行八个任务,同时最多运行两个任务,并打印开始和结束信息来展示并发上限的实际效果。
package main
import (
"fmt"
"sync"
"time"
)
func main() {
sem := make(chan struct{}, 2)
var wg sync.WaitGroup
for i := 0; i < 8; i++ {
wg.Add(1)
sem <- struct{}{}
go func(id int) {
defer wg.Done()
defer func() { <-sem }()
fmt.Println("start", id)
time.Sleep(20 * time.Millisecond)
fmt.Println("end", id)
}(i)
}
wg.Wait()
fmt.Println("done")
}errgroup 与 SetLimit
golang.org/x/sync/errgroup 包提供了 SetLimit,可以限制一组任务的并发数,并传递第一个错误。在许多情况下,它是更简洁的替代方案,但它属于外部包。
限流与工作池
工作池会复用一组固定的 goroutine,让它们从队列中获取任务。信号量限流则为每个任务启动一个 goroutine,但限制处于活动状态的 goroutine 数量。对于数量极大的任务,工作池更加精简;信号量则更容易直接添加到现有代码中。
选择限制值
对于数据库调用,请将限制值设置为不高于连接池大小。对于出站 HTTP 请求,请与主机的连接限制相匹配。限制过高会耗尽资源,限制过低则会浪费容量。
快速检查
请测试您对限流的了解。
总结
您学会了 goroutine 限流:
- 带缓冲的通道可以充当计数信号量
- 通过发送来获取许可,并在 defer 中通过接收来释放许可
- struct{} 元素不占用任何字节
- 与 WaitGroup 配合以等待任务完成
- 根据受保护资源的情况设置限制值
用 AI 导师学习 Go — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 51
- 课程
- 203
常见问题解答
「限制 Goroutine」课时是免费的吗?
是的 — 「限制 Goroutine」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。
「限制 Goroutine」这节课中我会学到什么?
控制并发量 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Go Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「限制 Goroutine」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Go Academy 课中编写并运行代码吗?
能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 令牌桶概念
- golang.org/x/time/rate
- 限制 Goroutine
- 退避与重试