Go 并发
2025-09-22 17:33
Go
0
0
0
0
标题录入
封面图
Go 语言(Golang)的并发模型是其一大亮点,它通过 **goroutine** 和 **channel** 实现高效的并发编程。下面我将从以下几个方面为你介绍 Go 的并发机制: --- ## 一、Goroutine(协程) ### 1.1 什么是 Goroutine? Goroutine 是 Go 中轻量级的线程,由 Go 运行时管理,而不是操作系统调度。你可以轻松地启动成千上万的 goroutine。 ### 1.2 如何启动一个 Goroutine? 使用 `go` 关键字来启动一个 goroutine: ```go func sayHello() { fmt.Println("Hello from goroutine") } func main() { go sayHello() time.Sleep(1 * time.Second) // 等待 goroutine 执行完毕 } ``` > 注意:主函数结束后,程序可能不会等待所有 goroutine 完成,因此需要适当等待(如 `time.Sleep()` 或使用 `sync.WaitGroup`)。 --- ## 二、Channel(通道) ### 2.1 什么是 Channel? Channel 是 goroutine 之间通信的管道,用于在不同 goroutine 之间传递数据。 ### 2.2 声明和使用 Channel ```go // 声明一个 string 类型的 channel ch := make(chan string) // 发送数据到 channel ch <- "hello" // 接收数据 msg := <-ch fmt.Println(msg) ``` ### 2.3 单向 Channel 可以声明只发送或只接收的 channel: ```go // 只能发送 chSend := make(chan<- int) // 只能接收 chRecv := make(<-chan int) ``` --- ## 三、Goroutine 与 Channel 的配合 ### 3.1 并发计算示例 ```go func sum(a []int, ch chan int) { total := 0 for _, v := range a { total += v } ch <- total } func main() { nums := []int{1, 2, 3, 4, 5} ch := make(chan int) go sum(nums, ch) result := <-ch fmt.Println("Sum:", result) } ``` --- ## 四、同步与互斥 ### 4.1 WaitGroup 用于等待多个 goroutine 完成: ```go var wg sync.WaitGroup func worker(id int) { defer wg.Done() fmt.Printf("Worker %d is running\n", id) } func main() { for i := 1; i <= 5; i++ { wg.Add(1) go worker(i) } wg.Wait() fmt.Println("All workers done") } ``` ### 4.2 Mutex(互斥锁) 用于保护共享资源,防止竞态条件: ```go var mu sync.Mutex var count int func increment() { mu.Lock() count++ mu.Unlock() } ``` --- ## 五、Select 语句 `select` 语句用于在多个 channel 操作中选择一个可执行的分支,类似于 `switch`。 ```go ch1 := make(chan int) ch2 := make(chan int) go func() { ch1 <- 42 }() go func() { ch2 <- 21 }() select { case msg1 := <-ch1: fmt.Println("Received from ch1:", msg1) case msg2 := <-ch2: fmt.Println("Received from ch2:", msg2) } ``` --- ## 六、Context(上下文) 用于控制 goroutine 的生命周期,常用于超时、取消等场景: ```go ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() go func(ctx context.Context) { select { case <-time.After(2 * time.Second): fmt.Println("Done") case <-ctx.Done(): fmt.Println("Cancelled:", ctx.Err()) } }(ctx) ``` --- ## 七、常见并发模式 | 模式 | 描述 | |------|------| | Worker Pool | 使用固定数量的 goroutine 处理任务 | | Fan-in/Fan-out | 将多个 channel 的输出合并,或将一个 channel 分发到多个 channel | | Pipeline | 用多个 stage 处理数据流 | --- ## 八、并发注意事项 - 避免共享内存,使用 channel 通信。 - 避免死锁(例如两个 goroutine 在等待对方释放资源)。 - 正确使用 `sync.WaitGroup` 和 `Mutex` 来同步。 --- 如果你有具体的问题,比如“如何用 Go 实现一个并发爬虫”、“goroutine 和线程的区别”或者“channel 的缓冲与非缓冲区别”,欢迎继续提问!我可以提供更详细的解释和代码示例。
上一篇:
Go 语言结构
标题录入,一次不能超过6条
炒股技巧
T:0.005208s,M:117.55 KB
返回顶部
留言
留言
评论