当前位置: 首页 > article >正文

16 - Go 协程(goroutine):从基础到实战

文章目录 16 - Go 协程goroutine从基础到实战什么是 goroutine 第一个 goroutinegoroutine 执行机制 关键模型GMP 模型 调度流程简化版 为什么 goroutine 很轻goroutine channel核心组合 channel 基础示例goroutine 通信 带缓冲 channelgoroutine 实战场景 并发任务处理 使用 WaitGroup 控制并发 并发安全Mutexgoroutine 常见坑必会❌ 主 goroutine 提前退出❌ 闭包变量问题经典面试题❌ goroutine 泄漏goroutine 调度细节进阶⏱ 抢占式调度Go 1.14 调度时机性能优化建议 控制 goroutine 数量 使用 sync.Pool 复用对象 合理使用 channel总结 goroutine 核心要点 并发三件套 一句话总结 面试高频问题 16 - Go 协程goroutine从基础到实战Go 的并发之所以强大不是因为它快而是因为它简单且优雅。在 Go 语言中并发编程的核心就是goroutine。它让你用极低的成本实现高并发是 Go 被称为“云原生语言”的关键原因之一。什么是 goroutinegoroutine 是 Go 语言中的轻量级线程用户态线程 特点占用内存极小初始 ~2KB创建成本极低由 Go runtime 调度而不是操作系统可以轻松创建成千上万个 第一个 goroutinepackagemainimport(fmttime)// 定义一个普通函数funchello(){fmt.Println(Hello, world!)// 打印一句话}funcmain(){gohello()// 使用 go 关键字启动一个 goroutine协程// 此时 hello() 会在一个新的协程中异步执行// main 函数不会等待它执行完time.Sleep(time.Second)// 让主 goroutine 休眠 1 秒// 作用防止 main 提前退出// 如果没有这行代码程序可能在 hello() 执行前就结束了} 注意1. goroutine 是异步执行的go hello()不会阻塞main 会继续往下执行2. main 退出 所有 goroutine 结束这是很多新手最容易踩的坑goroutine 执行机制 关键模型GMP 模型Go 的调度核心是名称含义GGoroutineM线程MachinePProcessor调度器 关系G任务 → P队列 → M执行 调度流程简化版goroutineG加入队列P 负责调度 GM线程执行 G遇到阻塞 → 切换其他 G 为什么 goroutine 很轻相比传统线程对比项线程goroutine创建成本高极低内存MB级KB级调度OSGo runtime切换慢快goroutine channel核心组合Go 并发哲学不要通过共享内存来通信而要通过通信来共享内存 channel 基础ch:make(chanint)示例goroutine 通信packagemainimportfmt// 定义一个 worker 函数接收一个 int 类型的 channelfuncworker(chchanint){ch-100// 向 channel 发送数据 100// 如果没有接收者这里会阻塞很关键}funcmain(){ch:make(chanint)// 创建一个无缓冲 channel同步 channel// 特点发送和接收必须同时准备好否则会阻塞goworker(ch)// 启动 goroutine 执行 worker// worker 会尝试向 channel 发送数据v:-ch// 从 channel 接收数据// 如果没有数据这里会阻塞直到有数据写入fmt.Println(v)// 输出接收到的值100} 带缓冲 channelpackagemainimportfmt// 定义 worker 函数参数是一个 int 类型的 channelfuncworker(chchanint){ch-100// 向 channel 发送数据 100// 因为是带缓冲 channel所以只要 buffer 没满就不会阻塞}funcmain(){ch:make(chanint,2)// 创建一个带缓冲的 channel容量为 2// 表示最多可以暂存 2 个 intch-1// 第一次发送放入 buffer[0]ch-2// 第二次发送放入 buffer[1]// 此时 buffer 已满2/2fmt.Println(-ch)// 从 channel 取出一个值1// buffer 腾出一个位置fmt.Println(-ch)// 再取出一个值2// 此时 buffer 为空goworker(ch)// 启动 goroutine 执行 worker// 因为 buffer 已经空出空间所以可以正常写入 100fmt.Println(-ch)// 从 channel 取出一个值100fmt.Println(main function)// 主函数继续执行不会等待 worker}输出1 2 100 main function实际运行逻辑是创建 buffer 2 的 channel写入 1、2buffer 满读取 1、2buffer 清空启动 goroutine 写入 100main 继续执行读取 100 特点不会立即阻塞类似队列goroutine 实战场景 并发任务处理packagemainimport(fmttime)// 定义一个任务函数模拟耗时操作functask(idint){fmt.Println(start,id)// 打印任务开始time.Sleep(time.Second)// 模拟耗时 1 秒的业务逻辑比如 IO / 网络 / DBfmt.Println(end,id)// 打印任务结束}funcmain(){fori:0;i10;i{gotask(i)// 启动 10 个 goroutine 并发执行 task// 每个 goroutine 处理一个 id}time.Sleep(2*time.Second)// 主 goroutine 休眠 2 秒// 作用防止 main 函数提前退出// 否则子 goroutine 还没执行完程序就结束了}输出start9start6start4start5start8start0start1start2start7start3end9end6end5end4end0end8end3end1end2end7 输出是“交错的” 重点goroutine 调度是抢占式 不可控顺序10 个 goroutine 同时进入调度队列Go runtime 自动调度执行执行顺序 完全不确定 使用 WaitGroup 控制并发packagemainimport(fmtsync)// 定义一个任务函数接收 id 和 WaitGroup 指针functask(idint,wg*sync.WaitGroup){deferwg.Done()// defer 保证函数结束时一定调用 Done()// 表示该 goroutine 执行完成计数器 -1fmt.Println(task:,id)// 模拟任务执行}funcmain(){varwg sync.WaitGroup// 创建 WaitGroup用于控制 goroutine 同步fori:0;i10;i{wg.Add(1)// 每启动一个 goroutine计数器 1// 表示“还有一个任务未完成”gotask(i,wg)// 启动 goroutine 执行任务// 注意传指针否则会拷贝 wg错误写法}wg.Wait()// 阻塞主 goroutine// 直到 wg 计数器变为 0所有任务完成}输出顺序不一的task:9task:0task:1task:2task:3task:4task:5task:6task:7task:8 推荐生产环境必须用 WaitGroup而不是 sleepWaitGroup 是 Go 中用于“等待一组 goroutine 完成”的标准同步工具本质是计数器控制并发生命周期。 并发安全Mutexpackagemainimport(fmtsync)// 全局变量共享资源多个 goroutine 会同时访问varcountint// 定义互斥锁用于保护共享变量 countvarmu sync.Mutex// 定义任务函数接收 WaitGroup 指针funcadd(wg*sync.WaitGroup){deferwg.Done()// goroutine 执行完成后通知 WaitGroup -1mu.Lock()// 加锁同一时刻只允许一个 goroutine 进入临界区count// 临界区对共享变量进行修改非原子操作mu.Unlock()// 解锁允许其他 goroutine 进入临界区}funcmain(){varwg sync.WaitGroup// 用于等待所有 goroutine 执行完成fori:0;i1000;i{wg.Add(1)// 每启动一个 goroutine计数 1goadd(wg)// 启动 goroutine 执行加法操作}wg.Wait()// 阻塞主 goroutine等待所有任务完成fmt.Println(count)// 输出最终结果1000} Go 设计哲学不要通过共享内存通信而要通过通信共享内存Mutex 的作用是保证共享资源在并发访问时的“互斥性”从而避免数据竞争保证程序结果正确。goroutine 常见坑必会❌ 主 goroutine 提前退出gofunc(){fmt.Println(hello)}() 可能不会执行✔ 解决WaitGroupchannel阻塞 main❌ 闭包变量问题经典面试题fori:0;i3;i{gofunc(){fmt.Println(i)}()} 可能输出3 3 3✔ 正确写法fori:0;i3;i{gofunc(iint){fmt.Println(i)}(i)}❌ goroutine 泄漏funcworker(chchanint){-ch// 永远等不到} 没有关闭 channel → goroutine 永久阻塞正确写法funcworker(chchanint){forv:rangech{fmt.Println(v)}}主函数ch:make(chanint)goworker(ch)ch-1ch-2close(ch)// 关键关闭 channelgoroutine 调度细节进阶⏱ 抢占式调度Go 1.14以前协程不会主动让出 CPU现在Go runtime 会强制抢占 优势防止某个 goroutine 长时间占用 CPU 调度时机goroutine 切换发生在channel 阻塞IO 阻塞系统调用runtime 主动调度性能优化建议 控制 goroutine 数量❌ 错误for{gotask()}✔ 正确使用 worker pooljobs:make(chanint,100)forw:0;w5;w{goworker(jobs)} 使用 sync.Pool 复用对象减少 GC 压力高并发场景 合理使用 channel不要滥用简单场景用锁更高效总结 goroutine 核心要点go关键字开启协程本质是用户态线程由 GMP 模型调度与 channel 配合使用最优雅 并发三件套goroutinechannelsyncWaitGroup / Mutex 一句话总结goroutine 让并发变简单但并发本身并不简单。 面试高频问题goroutine 和线程区别答轻量级线程由 Go runtime 管理。GMP 模型是什么答Go 运行时调度模型包含 Ggoroutine、M线程和 P处理器。channel 是怎么实现的答基于管道通信底层实现依赖于 goroutine。如何避免 goroutine 泄漏答确保所有 goroutine 执行完毕或使用 context 控制。select 的作用答多路复用用于等待多个 channel 操作。

相关文章:

16 - Go 协程(goroutine):从基础到实战

文章目录🚀 16 - Go 协程(goroutine):从基础到实战什么是 goroutine?🚀 第一个 goroutinegoroutine 执行机制🔥 关键模型:GMP 模型🧠 调度流程(简化版&#x…...

ApkShellext2:让Windows资源管理器也能“看懂“应用包文件

ApkShellext2:让Windows资源管理器也能"看懂"应用包文件 【免费下载链接】apkshellext Show app icons in windows explorer 项目地址: https://gitcode.com/gh_mirrors/ap/apkshellext 你是否曾在Windows资源管理器中面对一堆.apk、.ipa文件时感…...

船舶自动化中的数字化: 为什么可靠的边缘系统在海上至关重要?

前言海事行业正经历着深刻的技术变革。船舶不再是独立航行于海洋的孤立机械系统,而是日益成为互联互通、数据驱动的环境,导航、推进、安全和运营系统在其中持续交互。这场数字化转型,正重新定义船舶的设计、运营与维护方式。从驾控台系统、发…...

终极指南:如何用AEUX插件打通Sketch/Figma到After Effects的无缝工作流

终极指南:如何用AEUX插件打通Sketch/Figma到After Effects的无缝工作流 【免费下载链接】AEUX Editable After Effects layers from Sketch artboards 项目地址: https://gitcode.com/gh_mirrors/ae/AEUX 还在为设计到动画的转换效率低下而烦恼吗&#xff1f…...

美国AI,怎么也搞实名制了?

谁会受益,谁会付出代价? Anthropic毫无征兆地开始强推实名认证。 从今天起,Anthropic要求部分Claude用户提交政府证件和实时自拍,才能继续访问某些能力。 Anthropic官方表示,这一机制目前仅针对“少数使用场景”&am…...

终极指南:如何免费解锁AI编程助手高级功能

终极指南:如何免费解锁AI编程助手高级功能 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your trial request …...

Langchain学习笔记1-管道符|构建链路问题初探

Langchain学习笔记1-管道符|构建链路问题初探 问题 学习摘要记忆时,下面一段代码不太理解:变量x就是上一轮的输出吗?那第一次是怎么执行的?| 首先搞清| 的原理,Runnable 重写了__or__,继续点开函数coerce_t…...

Rust 所有权与生命周期实例讲解

Rust作为一门现代系统编程语言,其独特的所有权与生命周期机制是解决内存安全问题的核心设计。这些概念初看可能令人困惑,但通过实际案例剖析,我们能发现它们如何优雅地避免数据竞争和悬垂指针。本文将用三个典型场景,带你穿透理论…...

避坑指南:OpenMV做数字识别,为什么你的帧率总上不去?手把手教你性能调优

OpenMV数字识别性能调优实战:从卡顿到流畅的完整解决方案 当你兴奋地将OpenMV摄像头对准目标数字,准备大展身手时,却发现画面像老式幻灯片一样一帧一帧地跳动——这种体验想必不少开发者都深有体会。特别是在电子设计竞赛等实时性要求高的场景…...

飞牛OS新手必看:用acme.sh脚本一键搞定SSL证书,告别手动更新烦恼

飞牛OS SSL证书自动化管理:从零到精通的acme.sh实战指南 每次看到浏览器地址栏那个红色"不安全"警告,心里是不是咯噔一下?作为飞牛OS用户,你可能已经意识到SSL证书的重要性,但又被那些晦涩的命令行和繁琐的…...

跨平台文本编辑神器Notepad--:5个核心功能助你高效处理代码与文档

跨平台文本编辑神器Notepad--:5个核心功能助你高效处理代码与文档 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器,目标是做中国人自己的编辑器,来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/notepad-…...

Navicat重置试用期终极指南:免费无限使用Navicat Premium完整功能

Navicat重置试用期终极指南:免费无限使用Navicat Premium完整功能 【免费下载链接】navicat_reset_mac navicat mac版无限重置试用期脚本 Navicat Mac Version Unlimited Trial Reset Script 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac …...

如何用Stretchly打造健康工作习惯:休息提醒工具的完整使用指南

如何用Stretchly打造健康工作习惯:休息提醒工具的完整使用指南 【免费下载链接】stretchly The break time reminder app 项目地址: https://gitcode.com/gh_mirrors/st/stretchly 在现代数字工作环境中,长时间盯着电脑屏幕已成为常态&#xff0c…...

对比评测:DeOldify与其他主流图像上色模型效果差异

对比评测:DeOldify与其他主流图像上色模型效果差异 老照片承载着记忆,但褪色的黑白影像总让人觉得少了点什么。最近几年,AI图像上色技术发展飞快,从早期的简单着色,到现在能生成色彩自然、细节丰富的彩色照片&#xf…...

Android Studio中文界面完整汉化指南:三步实现母语开发环境

Android Studio中文界面完整汉化指南:三步实现母语开发环境 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本) 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack 还在为And…...

郭老师-人生进阶三铁律:认知升维,行动聚焦

人生进阶三铁律:认知升维,行动聚焦拉开人与人差距的,从来不是努力,而是你认知世界的维度。🌟 核心洞见 你是否常感困惑: 明明很努力,却始终原地打转?学了很多,却换不来真…...

LayerDivider:一键式智能分层革命,让插画师告别手工抠图时代

LayerDivider:一键式智能分层革命,让插画师告别手工抠图时代 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 想象一下这样的场景&…...

STM32硬件AES的GCM模式实战:为你的设备通信加上“防伪标签”

STM32硬件AES的GCM模式实战:为你的设备通信加上"防伪标签" 在物联网设备爆炸式增长的今天,安全通信已成为嵌入式系统设计的核心挑战。想象一下,当你的智能门锁接收到的开锁指令被黑客篡改,或者工业控制系统的关键参数在…...

Matlab高手进阶:用textscan函数解析日志文件,提取关键信息的完整流程

Matlab日志解析实战:textscan函数高效提取关键信息的全流程指南 当服务器日志像雪片般涌来时,工程师们常常面临一个共同困境——如何从海量非结构化文本中快速提取有价值的信息?Matlab的textscan函数正是解决这类问题的瑞士军刀。不同于简单的…...

SVN Update 冲突解决全攻略:从选项解析到实战决策

1. 当SVN Update遇到冲突时该怎么办? 第一次看到SVN update冲突提示时,我整个人都是懵的。屏幕上突然跳出一堆选项:p、df、e、mc、tc...这简直就像在玩解谜游戏。作为一个过来人,我完全理解这种手足无措的感觉。但别担心&#xf…...

2026 云安全深度复盘:AI 放大的系统性危机与防御实战 | Wiz 全球报告解读

当整个行业都在热议AI将带来"颠覆性"网络攻击时,Wiz Research发布的《2026云威胁回顾报告》却揭示了一个令人不安的真相:2025年全球云安全格局的最大威胁,并非那些科幻小说般的AI自主攻击,而是我们早已熟知的漏洞、密钥…...

Umi-OCR终极指南:完全免费的开源离线OCR解决方案

Umi-OCR终极指南:完全免费的开源离线OCR解决方案 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。内置多国语言库。…...

Go-CQHTTP终极指南:一站式构建智能QQ机器人助手

Go-CQHTTP终极指南:一站式构建智能QQ机器人助手 【免费下载链接】go-cqhttp cqhttp的golang实现,轻量、原生跨平台. 项目地址: https://gitcode.com/gh_mirrors/go/go-cqhttp 在当今数字化时代,智能聊天机器人已成为社群管理、自动化客…...

别再只把GAN当‘造假工具’了:从图像生成到数据增强,聊聊它在实际项目里的5种另类用法

GAN实战手册:超越图像生成的5个工业级应用场景 在咖啡厅里第一次听说GAN能生成以假乱真的人脸时,我像大多数开发者一样,把它归类为"酷炫但无用"的技术玩具。直到去年处理医疗影像数据集时,面对仅有200张标注样本的困境&…...

Novel-Downloader:200+网站小说下载终极指南,高效实现离线阅读

Novel-Downloader:200网站小说下载终极指南,高效实现离线阅读 【免费下载链接】novel-downloader 一个可扩展的通用型小说下载器。 项目地址: https://gitcode.com/gh_mirrors/no/novel-downloader 你是否曾经遇到过这样的情况:正在追…...

致远OA密码重置漏洞深度解析:从漏洞原理到防御策略

致远OA密码重置漏洞技术剖析与实战防御指南 在数字化转型浪潮中,企业办公自动化系统承载着核心业务流程与敏感数据,其安全性直接关系到企业命脉。致远OA作为国内广泛部署的企业级协同平台,近期曝出的密码重置漏洞引发了安全圈的高度关注。本文…...

从HOGP协议到内核驱动:深入解析BlueZ连接蓝牙手柄的全链路

1. 蓝牙HID设备与HOGP协议基础 第一次接触蓝牙手柄开发时,我被各种专业术语搞得晕头转向。直到把整个流程拆解成几个关键环节,才发现原来蓝牙手柄的工作原理就像快递配送系统一样有章可循。HOGP(HID Over GATT Profile)本质上是个…...

创新实训博客记录 | 2.用户模块实现(登录/个人信息等)

目录 1. 技术实现思路 2. 目前已实现接口 3. 关键业务流程说明 3.1 登录流程 3.2 个人资料与角色 3.3 用户、患者、医生关系 4. 总结 本周主要推进了后端的用户模块,进入到“可登录、可鉴权、可管理基础人员信息”的阶段。 当前已经完成用户认证、个人信息、…...

3个步骤:如何用ParsecVDisplay为Windows创建高性能虚拟4K显示器

3个步骤:如何用ParsecVDisplay为Windows创建高性能虚拟4K显示器 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd ParsecVDisplay是一款基于Parsec虚拟显示驱动技术的独…...

别再手动调格式了!用LaTeX + ctexart搞定中文期刊论文排版(附完整模板)

LaTeX ctexart:科研论文排版的终极效率方案 第一次投稿中文期刊时,我花了整整三天调整Word格式——标题字号不对、参考文献编号错乱、页眉页脚莫名其妙消失。直到实验室师兄扔给我一个.tex文件:"试试这个,点一下编译就行&qu…...