解锁 Go 并发超能力:Tutorials 用 5 个实战示例讲透 Goroutine、Channel 与 Select
【免费下载链接】tutorialsSource code from Jake Wright's YouTube tutorials项目地址: https://gitcode.com/gh_mirrors/tutorials5/tutorials
🚀 Tutorials 是 Jake Wright YouTube 编程教程的配套源码仓库,其中go/02-go-concurrency目录用5 个由浅入深的 Go 并发实战示例,帮你快速掌握 Goroutine、Channel 与 Select 三大核心机制。无需大段理论,跟着 5 个小文件就能建立完整的 Go 并发编程心智模型,是初学者难得的轻量级 Go 并发教程。
📦 项目概览:Go 并发教程源码都藏在哪?
仓库中 Go 相关内容分为两大部分:
| 目录 | 内容 | 定位 |
|---|---|---|
go/01-learn-go | 变量、循环、函数、结构体、指针等 9 个基础示例 | 并发学习的前置基础 |
go/02-go-concurrency | Goroutine、WaitGroup、Channel、Select、Worker 池 5 个并发示例 | 本文主角 |
建议先扫一眼 01-learn-go/07-functions.go 感受一下 Go 函数风格,再进入并发章节。下面 5 个示例难度递增,每个只聚焦一个知识点。
示例 1:一个go关键字,开启你的第一个 Goroutine
源码文件:go/02-go-concurrency/01-goroutine.go
func main() { go count("sheep") // 异步执行 count("fish") // 主线程执行 }核心就 3 行:在函数调用前加一个go,该函数就会在独立的 Goroutine 中并发运行。
💡关键认知
- Goroutine 是 Go 的轻量级协程,创建成本极低,可以轻松创建成千上万个
- 主函数
main一旦退出,整个程序立即结束——其他 Goroutine 会被"就地正法" - 这个示例故意让
count变成死循环:你会发现"数鱼"的主线程其实活不长
这一步帮你建立最朴素的心智模型:go前缀 = 并行执行。
示例 2:用 WaitGroup 优雅等待并发任务
源码文件:go/02-go-concurrency/02-wait-group.go
var wg sync.WaitGroup wg.Add(1) go func() { count("sheep") wg.Done() }() wg.Wait()解决示例 1 的"程序跑不完"问题,sync.WaitGroup是标准答案,核心就 3 个方法:
Add(n):声明要等待 n 个任务Done():每个任务结束时调用,计数减一Wait():阻塞主线程,直到计数归零
📌 记住这个"Add → Done → Wait"三部曲,它在真实项目(如并发爬虫、批量下载)中无处不在,是 Go 并发入门必会的同步工具。
示例 3:Channel 让数据在 Goroutine 之间安全流动
源码文件:go/02-go-concurrency/03-channels.go
c := make(chan string, 50) // 带缓冲的通道 go count("sheep", c) for msg := range c { fmt.Println(msg) }Go 并发哲学的名言是"不要通过共享内存来通信,而要通过通信来共享内存",Channel 就是这句话的载体:
c <- value向通道发送数据,<-c从通道接收数据make(chan string, 50)创建带 50 容量的缓冲通道,发送方不会被立刻阻塞range会持续接收,直到发送方close(c)关闭通道后自动退出
相比共享变量加锁,Channel 把"谁在什么时候改数据"的问题彻底交给了通道本身,代码更直观、更不易出竞态条件。
示例 4:Select 多路监听,像 switch 一样调度多个通道
源码文件:go/02-go-concurrency/04-select.go
select { case msg1 := <-c1: // 每 500ms 一条消息 fmt.Println(msg1) case msg2 := <-c2: // 每 2s 一条消息 fmt.Println(msg2) }当程序需要同时监听多个 Channel 时,select登场。它的玩法和switch几乎一致:
- 每个
case对应一个通道操作 - 哪个通道先有数据,就执行哪个分支(无数据时阻塞等待)
- 天然适合做超时控制、事件合并、心跳检测等场景
这个示例里两个 Goroutine 以不同频率向c1、c2发消息,主循环用select统一接收——一个极简的"事件循环"就完成了。
示例 5:终极实战——Worker 池并行计算斐波那契
源码文件:go/02-go-concurrency/05-fib.go
前面 4 个示例的积木,在这里拼成一个完整的生产者-消费者模型:
go worker(jobs, results) // 启动 4 个 worker // ... for i := 0; i < 100; i++ { jobs <- i } close(jobs)精妙之处有三个:
- 任务分发:100 个斐波那契计算任务丢进
jobs通道,4 个 worker 自动"抢活干" - 方向限定:
worker(jobs <-chan int, results chan<- int)用只读/只写通道声明接口,编译器帮你防止误用 - 结果回收:所有结果汇入
results通道,主循环收满 100 个即结束
这就是生产环境中最经典的 Worker 池模式:任务队列 + 固定数量工作协程,简单、可控、易扩展。
✅ 学习路线与源码获取
🗺️ 推荐学习顺序(与目录编号一致):
01-goroutine.go → 02-wait-group.go → 03-channels.go → 04-select.go → 05-fib.go每个文件都不超过 35 行,配合运行观察输出,1~2 小时即可通关全部 Go 并发示例。
想动手练习?克隆完整源码仓库:
git clone https://gitcode.com/gh_mirrors/tutorials5/tutorials仓库里还有go/01-learn-go的 9 个基础篇、Docker 与 Home Automation 实战模块,全部代码短小精悍,是系统入门多种技术的优质练习场。掌握这 5 个并发示例后,你已具备阅读和编写生产级 Go 并发程序的核心能力 💪。
【免费下载链接】tutorialsSource code from Jake Wright's YouTube tutorials项目地址: https://gitcode.com/gh_mirrors/tutorials5/tutorials
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考