发布于2026-07-10 阅读(0)
扫一扫,手机访问
Ubuntu 下 Go 并发编程实践指南

在 Ubuntu 上实践 Go 并发编程,其实比想象中更顺畅。不过,最终体验的好坏,一半取决于环境是否就绪,另一半则是对 Go 并发原语的掌握程度。下面就先从环境搭聊起。
包管理器安装是最快的途径:
sudo apt update && sudo apt install -y golang-go
如果要最新版本,官方压缩包安装更灵活:
wget https://golang.org/dl/go1.22.5.linux-amd64.tar.gz && sudo tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz
配置 PATH 也很简单:
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile && source ~/.profile
最后用 go version 验证一下,能正确输出版本号就算成功。
有了 Go 之后,下面的工具链基本是标配:
go install github.com/go-delve/delve/cmd/dlv@latest,断点调试必备。go test -race ./...,单元测试和基准测试均可用。go tool pprof,配合 net/http/pprof 或 runtime/pprof 使用。go run、go build、go test、go mod tidy,这些是日常高频命令。在 Go 里做并发,几个核心原语必须心里有数:
下面是一个典型的并发任务处理场景——限制并发度、收集结果,还支持超时与取消。
package main
import (
"context"
"fmt"
"runtime"
"sync"
"time"
)
type Task struct {
ID int
}
type Result struct {
TaskID int
Err error
}
// 模拟耗时任务
func (t Task) Process(ctx context.Context) (Result, error) {
select {
case <-time.After(100 * time.Millisecond): // 模拟IO
return Result{TaskID: t.ID}, nil
case <-ctx.Done():
return Result{TaskID: t.ID}, ctx.Err()
}
}
// 固定大小 Worker Pool
func WorkerPool(ctx context.Context, tasks []Task, concurrency int, timeout time.Duration) []Result {
var wg sync.WaitGroup
results := make(chan Result, len(tasks))
sem := make(chan struct{}, concurrency) // 并发信号量
for _, task := range tasks {
select {
case <-ctx.Done():
return nil
default:
}
wg.Add(1)
sem <- struct{}{} // 获取令牌
go func(t Task) {
defer wg.Done()
defer func() { <-sem }() // 释放令牌
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
res, err := t.Process(ctx)
select {
case results <- res:
case <-ctx.Done():
}
}(task)
}
// 等待全部完成或取消
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
select {
case <-done:
case <-ctx.Done():
}
close(results)
var out []Result
for r := range results {
out = append(out, r)
}
return out
}
func main() {
// 显式设置 P 数量(容器/虚拟机中尤为重要)
runtime.GOMAXPROCS(runtime.NumCPU())
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
tasks := make([]Task, 20)
for i := 0; i < len(tasks); i++ {
tasks[i] = Task{ID: i + 1}
}
start := time.Now()
results := WorkerPool(ctx, tasks, 5, 500*time.Millisecond)
elapsed := time.Since(start)
var ok, fail int
for _, r := range results {
if r.Err != nil {
fail++
} else {
ok++
}
}
fmt.Printf("完成: %d, 失败: %d, 耗时: %v\n", ok, fail, elapsed)
}
go run main.gogo test -race(将任务抽象为可测试函数后执行)runtime.NumGoroutine() 观察协程泄漏趋势实战中,新手最容易踩的坑几乎都在下面:
go test -race;阻塞/CPU 分析用 go tool pprof;运行时观测用 runtime.NumGoroutine() 与自定义指标。GOMAXPROCS=$(nproc),避免误用宿主机核心数。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8