本教程将指导你在Debian系统上使用Golang实现并发编程,涵盖环境准备、基础并发原语(goroutines、channels)、同步工具(sync.WaitGroup、sync.Mutex)及常见并发模式(worker pool、pipeline)。

在Debian上安装Golang需通过包管理器完成,步骤如下:
# 更新软件包索引sudo apt update# 安装Golang(默认版本为最新稳定版)sudo apt install golang-go# 验证安装(显示版本号即成功)go versionGoroutines是Go的核心并发单元,使用go关键字启动,无需手动管理生命周期。示例如下:
package mainimport ("fmt""time")func printNumbers() {for i := 1; i <= 5; i++ {fmt.Printf("Number: %dn", i)time.Sleep(1 * time.Second) // 模拟耗时操作}}func main() {go printNumbers() // 启动goroutine// 主goroutine继续执行for i := 1; i <= 5; i++ {fmt.Printf("Main: %dn", i)time.Sleep(1 * time.Second)}}说明:主goroutine与printNumbers goroutine并发执行,输出交替出现。
Channels用于goroutines之间的数据传递,避免共享内存的竞态条件。示例如下:
package mainimport "fmt"func worker(ch chan<- int) {for i := 1; i <= 5; i++ {ch <- i // 发送数据到channel}close(ch) // 关闭channel(通知接收方无更多数据)}func main() {ch := make(chan int) // 创建无缓冲channelgo worker(ch)// 启动worker goroutine// 从channel接收数据(阻塞直到有数据)for num := range ch {fmt.Printf("Received: %dn", num)}}说明:ch := make(chan int)创建无缓冲channel,close(ch)关闭channel,for num := range ch循环接收数据直到channel关闭。
sync.WaitGroup用于等待多个goroutines执行完毕,避免主goroutine提前退出。示例如下:
package mainimport ("fmt""sync""time")func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 函数结束时通知WaitGroupfmt.Printf("Worker %d startedn", id)time.Sleep(2 * time.Second) // 模拟耗时操作fmt.Printf("Worker %d finishedn", id)}func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1) // 增加WaitGroup计数器go worker(i, &wg) // 启动goroutine(传入WaitGroup指针)}wg.Wait() // 阻塞直到计数器归零fmt.Println("All workers finished")}说明:wg.Add(1)增加计数器,defer wg.Done()确保函数结束时计数器减1,wg.Wait()阻塞主goroutine直到计数器归零。
sync.Mutex用于保护共享资源,防止多个goroutines同时修改导致的数据不一致。示例如下:
package mainimport ("fmt""sync")var (counter intmutex sync.Mutex // 定义互斥锁)func increment() {mutex.Lock() // 加锁(阻塞直到获取锁)counter++ // 修改共享变量mutex.Unlock() // 解锁}func main() {var wg sync.WaitGroupfor i := 0; i < 1000; i++ {wg.Add(1)go func() {defer wg.Done()increment()}()}wg.Wait()fmt.Printf("Final counter: %dn", counter) // 输出: 1000}说明:mutex.Lock()和mutex.Unlock()包裹共享变量的修改操作,确保同一时刻只有一个goroutine能访问。
Worker Pool模式通过固定数量的goroutines处理任务,避免资源耗尽。示例如下:
package mainimport ("fmt""sync")func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {defer wg.Done()for job := range jobs {fmt.Printf("Worker %d processing job %dn", id, job)results <- job * 2 // 处理结果发送到results channel}}func main() {const numJobs = 5const numWorkers = 3jobs := make(chan int, numJobs)results := make(chan int, numJobs)var wg sync.WaitGroup// 启动worker goroutinesfor w := 1; w <= numWorkers; w++ {wg.Add(1)go worker(w, jobs, results, &wg)}// 发送任务到jobs channelfor j := 1; j <= numJobs; j++ {jobs <- j}close(jobs) // 关闭jobs channel(通知worker无更多任务)wg.Wait() // 等待所有worker完成close(results) // 关闭results channel// 打印处理结果for result := range results {fmt.Printf("Result: %dn", result)}}说明:numWorkers控制并发数量,jobs channel分发任务,results channel收集结果。
Pipeline模式将多个处理步骤串联,每个步骤由独立的goroutine完成,前一步的输出作为下一步的输入。示例如下:
package mainimport "fmt"// generate生成0~9的整数func generate() <-chan int {ch := make(chan int)go func() {for i := 0; i < 10; i++ {ch <- i}close(ch)}()return ch}// square计算输入整数的平方func square(in <-chan int) <-chan int {out := make(chan int)go func() {for i := range in {out <- i * i}close(out)}()return out}func main() {// 构建pipeline:generate -> squarefor num := range square(generate()) {fmt.Println(num) // 输出0,1,4,9,...,81}}说明:generate函数生成数据,square函数处理数据,pipeline模式提高了代码的可读性和可维护性。
sync.Mutex或sync.RWMutex保护。make(chan T))会阻塞发送/接收操作,缓冲channel(make(chan T, size))可提高吞吐量,但需根据场景选择。通过本教程,你已掌握Debian下Golang并发编程的基础知识。建议通过官方文档进一步学习select语句、context包等高级特性,提升并发编程能力。