在 Linux 下用 Go 写并发,核心就是 goroutine + channel + sync(标准库)。下面从基础到实战给你一个清晰说明。
Go 的并发非常轻量,用 go 关键字即可。
package main
import (
"fmt"
"time"
)
func sayHello() {
fmt.Println("Hello from goroutine")
}
func main() {
go sayHello() // 启动一个 goroutine
time.Sleep(time.Second) // 等待 goroutine 执行完
}
✅ 注意:main 函数退出,所有 goroutine 都会直接结束
✅ Linux 上 Go 默认会使用多核(GOMAXPROCS)
Go 推荐 “不要通过共享内存来通信,而要通过通信来共享内存”
ch := make(chan int)
go func() {
ch <- 42
}()
fmt.Println(<-ch)
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for v := range ch {
fmt.Println(v)
}
适合高并发任务处理(如爬虫、任务队列)
package main
import (
"fmt"
"sync"
)
func worker(id int, jobs <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for j := range jobs {
fmt.Printf("worker %d job %d\n", id, j)
}
}
func main() {
jobs := make(chan int, 10)
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, jobs, &wg)
}
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)
wg.Wait()
}
用于超时、取消(Linux 后台服务必备)
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("canceled")
return
default:
fmt.Println("working...")
time.Sleep(500 * time.Millisecond)
}
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
go worker(ctx)
time.Sleep(3 * time.Second)
}
等所有 goroutine 结束(上面已用)
var mu sync.Mutex
var count = 0
func add() {
mu.Lock()
count++
mu.Unlock()
}
只执行一次(如初始化)
var once sync.Once
func initConfig() {
once.Do(func() {
fmt.Println("init once")
})
}
# 查看 goroutine 数量
GODEBUG=schedtrace=1000 ./app
# 生成并查看 trace
go tool trace trace.out
# 检测 race 条件
go run -race main.go
| 场景 | 推荐方式 |
|---|---|
| 简单并发 | goroutine |
| goroutine 通信 | channel |
| 控制生命周期 | context |
| 资源同步 | sync.Mutex |
| 批量任务 | worker pool |
如果你愿意,可以告诉我:
我可以直接给你一个 适合你场景的 Go 并发模板。