Go 语言并发编程入门

2026-06-22 · 6 阅读 · 309字
Go

Go 语言并发编程入门

Goroutine

Goroutine 是 Go 并发编程的核心。它是一种轻量级线程,由 Go 运行时管理而非操作系统。创建 goroutine 的成本极低,初始栈大小仅几 KB,可根据需要动态增长。

go func() {
    fmt.Println("Hello from goroutine")
}()

Channel

Channel 是 goroutine 之间的通信管道,遵循 "Do not communicate by sharing memory; instead, share memory by communicating" 的设计哲学。

无缓冲 channel

无缓冲 channel 同步阻塞,发送和接收必须同时准备好:

ch := make(chan int)
go func() {
    ch <- 42
}()
value := <-ch

有缓冲 channel

有缓冲 channel 在缓冲区未满时不会阻塞:

ch := make(chan string, 3)
ch <- "a"
ch <- "b"
ch <- "c" // 缓冲区满之前不会阻塞

select 多路复用

select 语句允许 goroutine 同时等待多个 channel 操作:

select {
case msg := <-ch1:
    fmt.Println(msg)
case msg := <-ch2:
    fmt.Println(msg)
case <-time.After(1 * time.Second):
    fmt.Println("timeout")
}

WaitGroup

sync.WaitGroup 用于等待一组 goroutine 完成:

var wg sync.WaitGroup
for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(id int) {
        defer wg.Done()
        doWork(id)
    }(i)
}
wg.Wait()

Mutex

当多个 goroutine 需要访问共享资源时,使用 sync.Mutex 保护临界区:

var mu sync.Mutex
var counter int

for i := 0; i < 1000; i++ {
    go func() {
        mu.Lock()
        counter++
        mu.Unlock()
    }()
}

常见模式

生产者-消费者

func producer(ch chan<- int) {
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
}

func consumer(ch <-chan int) {
    for v := range ch {
        fmt.Println(v)
    }
}

Pipeline 模式

func gen(nums ...int) <-chan int {
    out := make(chan int)
    go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()
    return out
}

func sq(in <-chan int) <-chan int {
    out := make(chan int)
    go func() {
        for n := range in {
            out <- n * n
        }
        close(out)
    }()
    return out
}

注意事项

  • 避免 goroutine 泄漏:确保 goroutine 能正常退出
  • 使用 context 包管理取消信号和超时
  • 不要猜测 goroutine 的执行顺序,使用 channel 或 WaitGroup 同步
  • 对关闭的 channel 发送数据会 panic