Golang 并发编程入门:Goroutine 简介与基础用法
文章目录
- 一、什么是 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 的特点:
- 轻量级:内存开销非常小,大约只需 2KB。
- 非抢占式调度:Goroutine 自愿让出 CPU,通过协作完成任务切换。
- 并发与并行:Goroutine 提供并发模型,多个任务可以同时进行。
- 阻塞模型简化开发:避免了复杂的回调函数,使代码结构更加简洁。
二、如何启动 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 的关系
- 主 Goroutine:main 函数所在的 Goroutine,程序从这里开始运行。
- 子 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,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。