BUILD · THINK · WRITE
在暗夜里写清楚代码
记录 Go、后端工程、并发编程、设计模式与开发思考。

Go 语言实现的协程

Go 语言简单实现协程

Go 语言中的协程叫 goroutine。它是一种轻量级线程,由 Go 运行时负责调度。相比系统线程,goroutine 创建成本更低,写并发程序也更简单。

启动一个协程只需要在函数调用前加上 go 关键字:

go task()

1. 最简单的 goroutine

下面的例子中,sayHello 会在新的协程中执行。

package main

import (
	"fmt"
	"time"
)

func sayHello() {
	fmt.Println("hello goroutine")
}

func main() {
	go sayHello()

	time.Sleep(time.Second)
	fmt.Println("main finished")
}

说明:

  • go sayHello() 会启动一个新的 goroutine
  • main 函数本身也是一个 goroutine
  • 如果 main 结束,其他还没执行完的 goroutine 也会被直接结束。
  • 这里用 time.Sleep 是为了简单等待子协程执行完,但真实项目更推荐使用 sync.WaitGroup

2. 使用 WaitGroup 等待协程结束

sync.WaitGroup 用来等待一组协程执行完成。

package main

import (
	"fmt"
	"sync"
)

func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done()

	fmt.Println("worker", id, "running")
}

func main() {
	var wg sync.WaitGroup

	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go worker(i, &wg)
	}

	wg.Wait()
	fmt.Println("all workers finished")
}

说明:

  • wg.Add(1) 表示新增一个需要等待的任务。
  • defer wg.Done() 表示当前协程结束时通知 WaitGroup
  • wg.Wait() 会阻塞,直到所有任务都执行完成。

3. 使用 channel 在协程间通信

channel 是 Go 中用于协程之间通信的管道。一个协程可以向 channel 发送数据,另一个协程可以从中接收数据。

package main

import "fmt"

func producer(ch chan string) {
	ch <- "hello from producer"
}

func main() {
	ch := make(chan string)

	go producer(ch)

	message := <-ch
	fmt.Println(message)
}

说明:

  • make(chan string) 创建一个字符串类型的通道。
  • ch <- value 表示向通道发送数据。
  • value := <-ch 表示从通道接收数据。
  • 默认情况下,发送和接收都会阻塞,直到另一端准备好。

4. 综合示例:多个协程计算结果

下面的例子启动多个协程分别计算数字平方,然后通过 channel 把结果传回主协程。

package main

import (
	"fmt"
	"sync"
)

func square(n int, ch chan int, wg *sync.WaitGroup) {
	defer wg.Done()

	ch <- n * n
}

func main() {
	numbers := []int{1, 2, 3, 4, 5}
	ch := make(chan int)
	var wg sync.WaitGroup

	for _, n := range numbers {
		wg.Add(1)
		go square(n, ch, &wg)
	}

	go func() {
		wg.Wait()
		close(ch)
	}()

	for result := range ch {
		fmt.Println("result:", result)
	}
}

说明:

  • 每个数字都由一个独立的 goroutine 处理。
  • 子协程通过 channel 把结果发送给主协程。
  • 所有子协程结束后关闭 channel
  • for result := range ch 会一直读取通道,直到通道被关闭。

小结

Go 实现协程主要靠三个核心点:

语法或类型 作用
go func() 启动一个新的协程
sync.WaitGroup 等待多个协程执行完成
channel 在协程之间传递数据

简单记忆:goroutine 负责并发执行,WaitGroup 负责等待结束,channel 负责通信。

posted @ 2026-07-04 00:41  zhangsan213  阅读(5)  评论(0)    收藏  举报