Go语言多线程编程指南

B站影视 港台电影 2025-04-08 10:30 3

摘要:在 Go 语言中,多线程主要通过Goroutine和Channel实现。Go 的并发模型基于CSP(Communicating Sequential Processes)理论,强调通过通信共享内存,而非通过共享内存进行通信。以下是 Go 多线程的核心概念和实践

在 Go 语言中,多线程主要通过 GoroutineChannel 实现。Go 的并发模型基于 CSP(Communicating Sequential Processes) 理论,强调通过通信共享内存,而非通过共享内存进行通信。以下是 Go 多线程的核心概念和实践:

1. Goroutine

轻量级线程:Goroutine 是 Go 运行时管理的轻量级线程,创建和切换开销极小(通常几 KB 的栈内存)。启动方式:使用 go 关键字即可启动一个 Goroutine。

go

go func {

fmt.Println("Hello from Goroutine!")

}

2. 同步与通信

(1) Channel(通道)

用途:Goroutine 之间通过 Channel 传递数据,避免共享内存的竞态问题。类型无缓冲通道:同步通信,发送和接收必须同时就绪。

go

ch := make(chan int)

go func { ch

value :=

有缓冲通道:异步通信,缓冲区未满时发送不阻塞。

go

复制

ch := make(chan int, 3)

ch

ch

(2) WaitGroup

用途:等待一组 Goroutine 完成。

go

var wg sync.WaitGroup

for i := 0; i

wg.Add(1)

go func(i int) {

defer wg.Done

fmt.Println(i)

}(i)

}

wg.Wait

(3) Mutex(互斥锁)

用途:保护共享资源,避免数据竞争。

go

var counter int

var mu sync.Mutex

for i := 0; i

go func {

mu.Lock

counter++

mu.Unlock

}

}

3. 常见并发模式

(1) Worker Pool

使用有缓冲 Channel 分发任务给一组 Goroutine。

go

jobs := make(chan int, 100)

results := make(chan int, 100)

// 启动 3 个 Worker

for w := 1; w

go func(id int) {

for job := range jobs {

results

}

}(w)

}

// 分发任务

for i := 1; i

jobs

}

close(jobs)

// 收集结果

for i := 1; i

fmt.Println(

}

(2) Select

监听多个 Channel 的事件,处理超时或优先级。

go

select {

case msg1 :=

fmt.Println(msg1)

case msg2 :=

fmt.Println(msg2)

case

fmt.Println("Timeout")

}

(3) Context

管理 Goroutine 的生命周期(取消、超时等)。

go

ctx, cancel := context.WithTimeout(context.Background, 2*time.Second)

defer cancel

go func(ctx context.Context) {

select {

case

fmt.Println("Cancelled")

return

}

}(ctx)

4. 避免竞态条件

使用 go run -race main.go 检测数据竞争。优先使用 Channel 或 Mutex 保护共享资源。

5. 注意事项

Goroutine 泄漏:确保 Goroutine 能正常退出(如通过 context 或关闭 Channel)。闭包陷阱:在循环中启动 Goroutine 时,通过参数传递循环变量:

go

for i := 0; i

go func(x int) { // 正确做法:传递参数

fmt.Println(x)

}(i)

}

示例:并发 HTTP 请求

go

func fetch(url string, ch chan

start := time.Now

resp, err := http.Get(url)

if err != nil {

ch

return

}

secs := time.Since(start).Seconds

ch

}

func main {

urls := string{"https://google.com", "https://github.com"}

ch := make(chan string)

for _, url := range urls {

go fetch(url, ch)

}

for range urls {

fmt.Println(

}

}

Go 的并发模型简洁高效,但需谨慎处理同步和资源竞争问题。通过 Goroutine 和 Channel 的组合,可以轻松构建高并发的程序。

来源:老客数据一点号

相关推荐