目录

Go语言并发编程指南

Go 语言的 goroutine 和 channel 让并发编程变得简单而强大。

Goroutine

go
package main

import (
    "fmt"
    "time"
)

func sayHello(name string) {
    for i := 0; i < 3; i++ {
        fmt.Printf("%s: %d
", name, i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    go sayHello("A")
    go sayHello("B")

    time.Sleep(time.Second)
    fmt.Println("主线程结束")
}

Channel

go
// 无缓冲通道:同步通信
ch := make(chan string)
go func() {
    ch <- "hello"  // 发送(阻塞直到有人接收)
}()
msg := <-ch        // 接收
fmt.Println(msg)

// 有缓冲通道:异步通信
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
// ch <- 4  // 缓冲区满,阻塞
fmt.Println(<-ch)  // 1

Channel 方向

go
// 只发送通道
func producer(out chan<- int) {
    for i := 0; i < 5; i++ {
        out <- i
    }
    close(out)
}

// 只接收通道
func consumer(in <-chan int) {
    for num := range in {
        fmt.Println(num)
    }
}

func main() {
    ch := make(chan int)
    go producer(ch)
    consumer(ch)
}

select 多路复用

go
func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() {
        time.Sleep(1 * time.Second)
        ch1 <- "来自通道1"
    }()

    go func() {
        time.Sleep(2 * time.Second)
        ch2 <- "来自通道2"
    }()

    // 等第一个就绪的通道
    select {
    case msg := <-ch1:
        fmt.Println(msg)
    case msg := <-ch2:
        fmt.Println(msg)
    }

    // 超时控制
    select {
    case msg := <-ch1:
        fmt.Println(msg)
    case <-time.After(500 * time.Millisecond):
        fmt.Println("超时")
    }
}

sync.WaitGroup

go
func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            fmt.Printf("任务 %d 完成
", id)
        }(i)
    }

    wg.Wait()  // 等待所有 goroutine 完成
    fmt.Println("全部完成")
}

Worker Pool 模式

go
func worker(id int, jobs <-chan int, results chan<- int) {
    for job := range jobs {
        fmt.Printf("worker %d 处理任务 %d
", id, job)
        time.Sleep(time.Second)
        results <- job * 2
    }
}

func main() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)

    // 启动3个worker
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    // 发送5个任务
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)

    // 收集结果
    for r := 1; r <= 5; r++ {
        fmt.Println("结果:", <-results)
    }
}

context 超时控制

go
func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()

    go func(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("任务取消:", ctx.Err())
                return
            default:
                fmt.Println("工作中...")
                time.Sleep(500 * time.Millisecond)
            }
        }
    }(ctx)

    <-ctx.Done()
    fmt.Println("主程序结束")
}

总结

Go 的并发模型以 goroutine(轻量级线程)和 channel(通信管道)为核心。goroutine 创建成本低,channel 让数据安全地在 goroutine 间传递。select 实现多路复用,WaitGroup 等待任务完成,context 管理超时和取消。这套模型让并发编程既安全又高效。