Golang 并发编程入门:Goroutine 简介与基础用法

06-02 1045阅读

文章目录

      • 一、什么是 Goroutine?
        • 1、Goroutine 的特点:
        • 二、如何启动 Goroutine
          • 语法:
          • 示例 1:基本的 Goroutine 用法
          • 三、主 Goroutine 与子 Goroutine 的关系
            • 示例 2:主线程结束导致子 Goroutine 终止
            • 四、Goroutine 的参数传递
              • 示例 3:Goroutine 传递参数
              • 五、匿名函数中的变量捕获问题
                • 示例 4:错误的变量捕获
                • 修改后的代码:将变量作为参数传递
                • 六、使用 WaitGroup 等待 Goroutine 完成
                  • 示例 5:使用 WaitGroup
                  • 七、Goroutine 的典型应用场景
                  • 八、注意事项与最佳实践
                  • 九、小结

                    一、什么是 Goroutine?

                    Goroutine 是 Golang 中的一种轻量级线程,用于实现并发操作。与传统线程相比,Goroutine 的优势在于它具有更低的资源消耗和更高的效率。每个 Goroutine 在运行时被 Go 的调度器(Scheduler)管理,并且它们共享内存空间。这使得在单个系统线程上运行成千上万个 Goroutine 成为可能。

                    1、Goroutine 的特点:
                    1. 轻量级:内存开销非常小,大约只需 2KB。
                    2. 非抢占式调度:Goroutine 自愿让出 CPU,通过协作完成任务切换。
                    3. 并发与并行:Goroutine 提供并发模型,多个任务可以同时进行。
                    4. 阻塞模型简化开发:避免了复杂的回调函数,使代码结构更加简洁。

                    二、如何启动 Goroutine

                    要启动 Goroutine,我们只需要在函数调用前加上 go 关键字。此操作会将该函数在单独的 Goroutine 中异步执行,主程序不会等待它完成。

                    语法:
                    go 函数名(参数)
                    
                    示例 1:基本的 Goroutine 用法
                    package main
                    import (
                        "fmt"
                        "time"
                    )
                    func printMessage() {
                        fmt.Println("Goroutine is running!")
                    }
                    func main() {
                        go printMessage() // 启动 Goroutine
                        time.Sleep(1 * time.Second) // 暂停主线程,确保 Goroutine 执行完
                        fmt.Println("Main function is done.")
                    }
                    

                    输出:

                    Goroutine is running!  
                    Main function is done.
                    

                    解释:

                    • 主 Goroutine(即 main 函数)立即启动了一个子 Goroutine 来运行 printMessage 函数。
                    • 如果没有 time.Sleep,主 Goroutine 可能会在子 Goroutine 还未执行时结束,导致没有输出。

                      三、主 Goroutine 与子 Goroutine 的关系

                      1. 主 Goroutine:main 函数所在的 Goroutine,程序从这里开始运行。
                      2. 子 Goroutine:由主 Goroutine 或其他 Goroutine 创建的 Goroutine。

                      关键点:如果主 Goroutine 结束,所有未完成的子 Goroutine 也会被强制终止。

                      示例 2:主线程结束导致子 Goroutine 终止
                      package main
                      import (
                          "fmt"
                          "time"
                      )
                      func main() {
                          go func() {
                              time.Sleep(2 * time.Second)
                              fmt.Println("This message may never appear.")
                          }()
                          fmt.Println("Main function is done.")
                          // 主 Goroutine 立即结束,子 Goroutine 没有机会完成
                      }
                      

                      输出:

                      Main function is done.
                      

                      解释:

                      • 主 Goroutine 结束时,所有未完成的子 Goroutine 会立即停止,因此不会看到子 Goroutine 的输出。

                        四、Goroutine 的参数传递

                        在 Golang 中,Goroutine 支持传递参数,但需要注意是按值传递,而不是按引用。

                        示例 3:Goroutine 传递参数
                        package main
                        import (
                            "fmt"
                        )
                        func printNumber(num int) {
                            fmt.Println("Number:", num)
                        }
                        func main() {
                            for i := 1; i 
                                go printNumber(i) // 启动 Goroutine 传递参数
                            }
                            fmt.Scanln() // 等待用户输入,防止程序提前结束
                        }
                        
                            for i := 1; i 
                                go func() {
                                    fmt.Println(i) // 捕获的可能是循环结束后的 i
                                }()
                            }
                            time.Sleep(1 * time.Second)
                        }
                        
                            fmt.Println(n)
                        }(i)
                        
                            defer wg.Done() // Goroutine 完成时调用 Done()
                            fmt.Println(msg)
                        }
                        func main() {
                            var wg sync.WaitGroup
                            wg.Add(3) // 等待 3 个 Goroutine
                            go printMessage("Hello", &wg)
                            go printMessage("from", &wg)
                            go printMessage("Goroutine!", &wg)
                            wg.Wait() // 等待所有 Goroutine 完成
                            fmt.Println("All Goroutines are done.")
                        }
                        
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码