开发者

Go语言使用Goroutine并发打印的项目实践

目录
  • 一、为什么学习 Goroutine?
  • 二、实战目标
  • 三、基础版本:启动多个 Gojsroutine
    • 运行结果(示例):
  • 四、问题:主程序过早退出
    • 五、进阶版本:使用 WaitGroup 等待所有 Goroutine 完成
      • 输出示例:
    • 六、重点知识点解析
      • 1.go关键字
      • 2.sync.WaitGroup
      • 3.defer用法
    • 七、延伸思考
      • 八、真实应用场景举例
        • 九、小结

          在本篇文章中,我们将从最基础的 Goroutine 并发模型入手,逐步掌握 Go 语言中并发控制的核心思想。通过一个简单的“并发打印任务”案例,掌握 Goroutine 的使用、输出顺序的控制、主协程退出时机等关键知识。

          一、为什么学习 Goroutine?

          Goroutine 是 Go 语言最核心的并发原语。相比于线程,它更加轻量:

          • 启动成本极低(大约只需 2KB 内存)
          • 数量可以轻松达到上万甚至百万级
          • 使用非常简单,只需一个 go 关键字

          Go 的并发理念是:不要通过共享内存来通信,而要通过通信来共享内存。

          掌握 Goroutine,是理解 Go 并发模型的第一步。

          二、实战目标

          我们将实现一个小项目:

          1. 启动多个 Goroutine 并发打印任务信息
          2. 每个任务打印固定内容
          3. 确保主程序等待所有任务完成
          4. 引入 sync.WaitGroup 实现同步控制

          三、基础版本:启动多个 Goroutine

          下面是最简单的 Goroutine 并发打印实现:

          package main
          
          import (
              "fmt编程"
              "time"
          )
          
          func printTask(id int) {
              fmt.Printf("任务 %d 正在执行\n", id)
          }
          
          func main() {
              for i := 1; i <= 5; i++ {
                  go printTask(i)
              }
          
              // 给协程一点时间完成(不推荐的方式)
              time.Sleep(time.Second)
              fmt.Println("主程序结束")
          }
          

          运行结果(示例):

          任务 2 正在执行

          任务 4 正在执行

          任务 1 正在执行

          任务 3 正在执行

          任务 5 正在执行

          主程序结束

          你会注意到,输出顺序可能与代码中的顺序不同,这是并发执行的结果。

          四、问题:主程序过早退出

          在上面例子中我们使用了 time.Sleep 来“凑时间”,这是一种不可靠且危险的方式。如果任务执行时间更长,就会被主程序强制退出。

          为了解决这个问题,我们引入 sync.WaitGroup

          五、进阶版本:使用 WaitGroup 等待所有 Goroutine 完成

          package main
          
          import (
              "fmt"
              "sync"
              "time"
          )
          
          // 模拟执行任务
          func printTask(id int, wg *sync.WaitGroup) {
              defer wg.Done() // 标记一个任务完成
              fmt.Printf("任http://www.devze.com务 %d 开始执行\n", id)
              time.Sleep(tim编程客栈e.Duration(id) * 200 * time.Millisecond) // 模拟不同任务耗时
              fmt.Printf("任务 %d 执行完毕\n", id)
          }
          
          func main() {
              var wg sync.WaitGroup
          
              taskCount := 5
              for i := 1; i <= taskCount; i++ {
                  wg.Add(1) // 增加一个任务
                  go printTask(i, &wg)
              }
          
              wg.Wait() // 等待所有任务完成
              fmt.Println("所有任务完成,主程序退出")
          }
          

          输出示例:

          任务 1 开始执行

          任务 2 开始执行

          任务 3 开始执行

          任务 4 开始执行

          任务 5 开始执行

          任务 1 执行完毕

          任务 2 执行完毕

          任务 3 执行完毕

          任务 4 执行完毕

          任务 5 执行完毕

          所有任务完成,主程序退出

          六、重点知识点解析

          1.go关键字

          只需在函数前加 go,即可将该函数交由调度器异步执行,立即返回

          2.sync.WaitGroup

          • wg.Add(n):添加 n 个任务
          • wg.Done():在任务完成后调用
          • wg.Wait():阻塞主线程,直到所有任务完成

          3.defer用法

          使用 defer wg.Done() 可以确保即使函数中途返回也能正确减计数。

          七、延伸思考

          • 若有 10万个任务要并发执行,Goroutine 是否能承载?(答案是:可以,但建议使用javascript并发控制池)
          • 如果某个任务失败,是否能提前取消其他任务?(答案是:可以结合 context 实现)

          八、真实应用场景举例

          • 批量调用多个接口(如:并发请求天气接口、发邮件)
          • 批量处理文件(压缩、上传、转码)
          • 并发爬虫(抓取多个页面)
          • 消息队列并发消费任务

          九、小结

          本文通过“并发打印任务”这一简单示例,向你展示了 Go 并发编程的基本能力:

          • 启动 Goroutine 的方法
          • 并发任务间的非确定性
          • 如何使用 WaitGroup 来保证主程序的正确退出
          • Goroutine 的轻量特性,适合高并发场景

          并发是 Go 的灵魂,控制好协程的生命周期和调度能力,将直接影响系统的健壮性与性能。

          到此这篇关于Go语言使用Goroutine并发打印的项目实践的文章就介绍到这了,更多相关Go Goroutine并发打印内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)! 

          0

          上一篇:

          下一篇:

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          最新开发

          开发排行榜