Go通过goroutine、channel及同步原语处理并发:用go启动轻量级goroutine,sync.WaitGroup管理生命周期,channel安全传递数据,sync.Mutex保护共享资源,组合使用可应对大部分并发需求。
Go语言处理并发问题的核心三板斧,其实就是goroutine、channel和同步原语。很多新手一上来就被各种术语绕晕,但别急,我们拆开看就清晰了。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
首先,启动一个并发任务非常简单——用go关键字就能开一个goroutine。这相当于轻量级的“线程”,实际开销极小,跑上几千个都不成问题。来看一个最直接的例子:
func main() {
go myFunction() // 启动一个新的goroutine来执行myFunction
// 主goroutine继续执行其他任务
}
func myFunction() {
// 这里是你的并发任务代码
}
但问题来了:开了这么多goroutine,怎么知道它们都跑完了?这时候就需要sync.WaitGroup登场了。它就像一个计数器,每启动一个goroutine就加一,跑完一个就减一,主线程等计数器归零再继续往下走。下面这个例子循环启动5个goroutine,并等它们全部结束:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1) // 为每个goroutine增加一个计数
go func(i int) {
defer wg.Done() // 当goroutine完成时,减少计数
fmt.Printf("Goroutine %d\n", i)
}(i)
}
wg.Wait() // 等待所有goroutines完成
}
那goroutine之间怎么交换数据?直接用共享变量加锁当然行,但Go推荐用channel——一种类型安全的通信管道。想象一下,一个goroutine往管道里丢数据,另一个从管道里取,天然避免竞态。下面的例子中,一个匿名goroutine不断往channel里发整数,主goroutine通过range收数据,收到10就关闭管道:
package main
import "fmt"
func main() {
data := make(chan int)
go func() {
for i := 0; ; i++ {
data <- i // 将数据发送到channel
}
}()
for num := range data {
if num >= 10 {
close(data) // 关闭channel,表示不再发送数据
break
}
fmt.Println(num)
}
}
最后,如果必须保护共享资源(比如全局计数器),就用sync.Mutex或sync.RWMutex锁住临界区。下面这个例子启动1000个goroutine并发递增一个计数器,每个都用mutex.Lock()和mutex.Unlock()保证数据安全:
package main
import (
"fmt"
"sync"
)
var counter int
var mutex sync.Mutex
func increment() {
mutex.Lock() // 加锁
counter++ // 修改共享资源
mutex.Unlock() // 解锁
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
increment()
}()
}
wg.Wait()
fmt.Println("Counter:", counter)
}
实际项目中,往往需要把这些工具组合起来用。比如用channel传递任务、用WaitGroup控制生命周期、用Mutex保护关键状态。掌握这几种基本模式,绝大部分并发需求都能轻松应对。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述