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

二、如何启动 Goroutine

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

语法:
go 函数名(参数)
示例 1:基本的 Goroutine 用法
package mainimport ("fmt""time"
)func printMessage() {fmt.Println("Goroutine is running!")
}func main() {go printMessage() // 启动 Goroutinetime.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. 主 Goroutinemain 函数所在的 Goroutine,程序从这里开始运行。
  2. 子 Goroutine:由主 Goroutine 或其他 Goroutine 创建的 Goroutine。

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

示例 2:主线程结束导致子 Goroutine 终止
package mainimport ("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 mainimport ("fmt"
)func printNumber(num int) {fmt.Println("Number:", num)
}func main() {for i := 1; i <= 3; i++ {go printNumber(i) // 启动 Goroutine 传递参数}fmt.Scanln() // 等待用户输入,防止程序提前结束
}

输出(可能):

Number: 1  
Number: 2  
Number: 3

五、匿名函数中的变量捕获问题

Goroutine 常与匿名函数一起使用,但要小心变量捕获问题。在循环中启动 Goroutine 时,匿名函数可能捕获的不是当前迭代变量的值,而是循环结束后的变量。

示例 4:错误的变量捕获
package mainimport ("fmt""time"
)func main() {for i := 1; i <= 3; i++ {go func() {fmt.Println(i) // 捕获的可能是循环结束后的 i}()}time.Sleep(1 * time.Second)
}

输出:

4  
4  
4
修改后的代码:将变量作为参数传递
go func(n int) {fmt.Println(n)
}(i)

六、使用 WaitGroup 等待 Goroutine 完成

time.Sleep 不是等待 Goroutine 完成的最佳方式。Go 提供了 sync.WaitGroup 来管理多个 Goroutine 的同步。

示例 5:使用 WaitGroup
package mainimport ("fmt""sync"
)func printMessage(msg string, wg *sync.WaitGroup) {defer wg.Done() // Goroutine 完成时调用 Done()fmt.Println(msg)
}func main() {var wg sync.WaitGroupwg.Add(3) // 等待 3 个 Goroutinego printMessage("Hello", &wg)go printMessage("from", &wg)go printMessage("Goroutine!", &wg)wg.Wait() // 等待所有 Goroutine 完成fmt.Println("All Goroutines are done.")
}

输出:

Hello  
from  
Goroutine!  
All Goroutines are done.

解释:

  • wg.Add(n) 表示需要等待 n 个 Goroutine 完成。
  • 每个 Goroutine 结束时调用 wg.Done()
  • wg.Wait() 会阻塞主 Goroutine,直到所有任务完成。

七、Goroutine 的典型应用场景

  1. I/O 并发:处理大量网络请求,减少响应时间。
  2. 后台任务:执行定时任务、日志记录等。
  3. 并行计算:分布计算任务,提高程序性能。
  4. 定时器与延时操作:如每隔一段时间执行某个操作。

八、注意事项与最佳实践

  1. 避免死锁:当 Goroutine 等待彼此时可能出现死锁,应小心处理共享资源。
  2. 合理使用 WaitGroup 和 Channel:确保 Goroutine 的同步与通信。
  3. 避免启动过多 Goroutine:虽然 Goroutine 轻量,但过多的 Goroutine 也会占用系统资源。
  4. 调试工具:使用 go tool tracepprof 进行性能调优和调试。

九、小结

Goroutine 是 Golang 的强大并发工具,其高效、易用的特点让它成为开发者实现并发程序的首选。在这篇博客中,我们介绍了 Goroutine 的基础用法、参数传递和同步机制,并演示了常见的应用场景和注意事项。


在下一篇博客中,我将详细介绍 通道(Channel) 的使用,它是 Goroutine 之间进行通信的主要工具。敬请期待!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/454417.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka之消费者客户端

1、历史上的二个版本 与生产者客户端一样&#xff0c;在Kafka的发展过程当中&#xff0c;消费者客户端主要有两个大的版本&#xff1a; 旧消费者客户端&#xff08;Old Consumer&#xff09;&#xff1a;基于Scala语言开发的版本&#xff0c;又称为Scala消费者客户端。新消费…

rpm 命令

rpm&#xff08;Red Hat Package Manager&#xff09;是 Red Hat Linux 及其衍生发行版&#xff08;如 CentOS、Fedora&#xff09;中用于管理软件包的系统。它允许用户安装、卸载、升级、查询和验证软件包。 一、安装软件包 &#xff08;1&#xff09;安装一个 RPM 软件包&a…

高并发下如何保证接口的幂等性?

前言 接口幂等性问题,对于开发人员来说,是一个跟语言无关的公共问题。本文分享了一些解决这类问题非常实用的办法,绝大部分内容我在项目中实践过的,给有需要的小伙伴一个参考。 不知道你有没有遇到过这些场景: 有时我们在填写某些form表单时,保存按钮不小心快速点了两次…

十二、【智能体】深入剖析:大模型节点的全面解读,举例说明,教你如何在扣子中嵌入代码

大模型节点 大模型节点主要分为5部分&#xff1a; 处理类型 单次批处理 模型类型&#xff1a;目前可以选择的模型有 豆包、通义千问、智谱、MinMax和Kimi输入:此时的参数可以被下面的提示词所用提示词&#xff1a;给大模型使用的提示词输出&#xff1a;经过此大模型处理后的输…

Vehicle Spy3.9如何新建工程—总览

1&#xff1a;写作目的 学习和精通SPY的使用&#xff0c;对于spy&#xff0c;目前主要是通用系用的比较多&#xff0c;本身spy的生产厂家英特佩斯也是美国的公司&#xff0c;除了软件自带教程。中文网上很少能找到相关的中文教程。 故写下这篇文章&#xff0c;帮助自己和大家…

Ubuntu(22.04)本地部署Appsmith

Ubuntu&#xff08;22.04&#xff09;安装Appsmith 简要介绍 Appsmith 是一个开源的低代码开发平台&#xff0c;旨在帮助开发者和非开发者快速构建定制化的内部应用程序和管理工具。通过直观的拖拽界面和丰富的预配置组件&#xff0c;Appsmith 让用户无需编写大量代码即可创建…

软件工程的学习之详细绪论

软件的定义 软件是程序和所有使程序正确运行所需要的相关文档和配置信息。 Software Program Data Document 一、软件危机&#xff1a; 软件开发和维护过程中遇到的一系列严重问题。 二、具体表现&#xff1a; 1、产品不符合用户的实际需要&#xff1b; 2、软件开发生产率…

Sigrity 共模电感的S-parameter仿真数据导入

下载S4P参数 https://ds.murata.co.jp/simsurfing/cmcc.html?partnumbers%5B%22DLW32MH101XT2%22%5D&oripartnumbers%5B%22DLW32MH101XT2L%22%5D&rgearjomoqke&rgearinfocom&md51729525489334# 下载S4P参数&#xff1b; DLW32MH101XT2.s4p Sigrity 使用-dif…

Mac电脑:资源库Library里找不到WebServer问题的解决

今天看到一本书里写到Windows电脑自带IIS Web服务器&#xff0c;好奇了一下下&#xff0c;mac电脑自带的又是什么服务器呢&#xff1f;经查询&#xff0c;原来是Apache服务器&#xff0c;这个名字我很熟悉。只是如何设置呢&#xff1f;我从来没用过&#xff0c;于是试验了一番。…

如何看待AI技术的应用前景?

人工智能&#xff1a;引领未来的变革力量 在当今快速变化的科技时代&#xff0c;人工智能&#xff08;AI&#xff09;作为一项前沿技术&#xff0c;已然成为推动全球各行各业变革的核心驱动力。随着人工智能技术的不断发展&#xff0c;其广泛的应用前景和深远的影响力&#xf…

Lua环境安装

软考鸭微信小程序 学软考,来软考鸭! 提供软考免费软考讲解视频、题库、软考试题、软考模考、软考查分、软考咨询等服务 Lua是一种轻量级、小巧且易于嵌入应用程序的脚本语言&#xff0c;广泛用于游戏开发、Web开发、自动化脚本等领域。本文将详细介绍如何在不同操作系统上安装L…

深度学习 基本函数01

np.dot 是 NumPy 库中的一个函数&#xff0c;用于计算两个数组的点积&#xff08;也称为内积或数量积&#xff09;。点积是两个向量的对应元素乘积之和。 np.random.normal 是 NumPy 库中的一个函数&#xff0c;用于生成符合正态分布&#xff08;也称为高斯分布&#xff09;的…

vue3-高德地图天气小组件

效果图 使用方法 <weather-view type"rect-solid" :borderColor"[#7ACAEC, #068BBD]"></weather-view>天气图标文件夹 本来想全弄成svg动态图片的,但找了很久都没找到对应的图(只找到了几个),于是就暂时搁置了 组件全代码如下 注意getWeat…

缓存框架JetCache源码解析-缓存定时刷新

作为一个缓存框架&#xff0c;JetCache支持多级缓存&#xff0c;也就是本地缓存和远程缓存&#xff0c;但是不管是使用着两者中的哪一个或者两者都进行使用&#xff0c;缓存的实时性一直都是我们需要考虑的问题&#xff0c;通常我们为了尽可能地保证缓存的实时性&#xff0c;都…

酒吧收银系统解决方案——未来之窗行业应用跨平台架构

一、酒吧管理数字化 1. 提高效率&#xff1a;能够快速处理订单&#xff0c;减少顾客等待时间&#xff0c;提高服务效率&#xff0c;从而提升顾客满意度。 2. 精确计费&#xff1a;准确计算酒水、小吃等各类消费项目的费用&#xff0c;避免人工计算错误导致的经济损失。 3. 库存…

vue后台管理系统从0到1(5)

文章目录 vue后台管理系统从0到1&#xff08;5&#xff09;完善侧边栏修改bug渲染header导航栏 vue后台管理系统从0到1&#xff08;5&#xff09; 接上一期&#xff0c;我们需要完善我们的侧边狼 完善侧边栏 我们在 element 组件中可以看见&#xff0c;这一个侧边栏是符合我们…

windows下Qt的安装方法

Qt Creator是个人非常喜欢的一款开发工具&#xff0c;喜欢用其来开发C和CPC平台项目&#xff0c;当然也可以用其来开发Android和Auto平台项目&#xff0c;但其现在采用离线安装&#xff0c;限于网络问题&#xff0c;安装速度非常慢。 现在介绍一种可以完成快速的安装方法。 下…

群晖通过 Docker 安装 MySQL

1. 打开 Docker 应用&#xff0c;并在注册表搜索 MySQL 2. 下载 MySQL 镜像&#xff0c;并选择版本 3. 在 Docker 文件夹中创建 MySQL&#xff0c;并创建子文件夹 4. 设置权限 5. 选择 MySQL 映像运行&#xff0c;创建容器 6. 配置 MySQL 容器 6.1 使用高权限执行容器 6.2 启…

圆周率的估算

圆周率的估算有多种方案&#xff1a; 方案一&#xff1a;无穷级数4/1 - 4/3 4/5 - 4/7 ……的和是圆周率π&#xff0c;这一无穷级数前n项的和即可估算圆周率值。 方案二&#xff1a;利用求单位正方形与内接圆面积的比例关系来求的π的近似值。单位圆的1/4面积是一个扇形&am…