尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Go 的 select 实战:超时、非阻塞收发与优雅退出的三个套路
Go 的 select 实战:超时、非阻塞收发与优雅退出的三个套路很多人学 Go 并发,select只会写「从多个 channel 里随便读一个」。但实战里select真正好用的是三个套路:给操作加超时、非阻塞地试探 channel、以及优雅关闭 goroutine。这三个不掌握,写出来的并发代码要么卡死,要么泄漏 goroutine。这篇一个一个过。套路一:给 channel 操作加超时朴素写法:直接从 channel 读,读不到就永远阻塞。// 危险:worker 出问题没往 ch 写,这里会永久卡住funcwaitResult(ch-chanint)int{return-ch}生产环境这种代码就是定时炸弹——上游一旦不响应,这个 goroutine 就永远挂在这里,连带上游的资源也释放不掉。正确做法是用select配一个time.After:importtimefuncwaitResult(ch-chanint)(int,error){select{casev:-ch:returnv,nilcase-time.After(2*time.Second):// 超过 2 秒没结果就返回错误,不再干等return0,fmt.Errorf(timeout waiting for result)}}time.After(d)返回一个 channel,d时间后会往里塞一个值。select会同时监听结果 channel 和这个定时 channel,哪个先来走哪个。一个坑:time.After在超时前不会被 GC 回收。如果你在一个高频循环里用它,会短暂堆积大量 Timer。循环内的超时应改用time.NewTimer并手动Stop:funcwaitResultLoop(ch-chanint){timer:time.NewTimer(2*time.Second)defertimer.Stop()// 用完及时释放,避免 Timer 堆积select{casev:-ch:fmt.Println(v)case-timer.C:fmt.Println(timeout)}}套路二:非阻塞收发有时你不想等,只想「试一下,能读就读,不能读就算了」。关键是给select加一个default分支——只要有default,select就永远不会阻塞。// 非阻塞读:channel 里有数据就拿,没有就走 defaultfunctryRead(ch-chanint){select{casev:-ch:fmt.Println(got:,v)default:fmt.Println(nothing ready, skip)}}// 非阻塞写:channel 满了就丢弃,不阻塞生产者functrySend(chchan-int,vint)bool{select{casech-v:returntruedefault:returnfalse// 缓冲满了,主动丢弃(比如做限流/降级)}}非阻塞写在实战里特别有用:比如做一个「有界的事件上报队列」,队列满了宁可丢事件也不能阻塞主流程,trySend就是标准写法。套路三:优雅退出 goroutine启动了 goroutine 却没法通知它退出,是 Go 里最常见的泄漏源。标准解法是用一个donechannel(或context)配select:funcworker(jobs-chanint,done-chanstruct{}){for{select{casejob:-jobs:process(job)case-done:// 收到退出信号,清理后返回,goroutine 正常结束fmt.Println(worker exiting)return}}}funcmain(){jobs:make(chanint)done:make(chanstruct{})goworker(jobs,done)jobs-1jobs-2close(done)// 关闭 done,所有监听它的 select 都会立刻收到零值time.Sleep(100*time.Millisecond)// 等 worker 打印退出(实际用 WaitGroup)}funcprocess(nint){fmt.Println(processing,n)}这里的精髓是close(done)而不是往里发值:关闭 channel 后,所有从它读取的select分支都会立刻返回(读到零值),所以能一次性通知任意数量的 goroutine 退出,不用给每个 goroutine 单独发信号。实际项目里更推荐直接用context.Context,它就是把这套donechannel 封装好了,还能级联取消:funcworker(ctx context.Context,jobs-chanint){for{select{casejob:-jobs:process(job)case-ctx.Done():return// ctx 被 cancel 或超时,退出}}}小结超时:selecttime.After,别裸读 channel;循环里改用time.NewTimerStop避免 Timer 堆积。非阻塞:加default分支,select就永不阻塞,适合做「能读就读、队满就丢」的降级逻辑。优雅退出:select监听done/ctx.Done(),用close(done)一次性通知所有 goroutine 退出,避免泄漏。一句话记忆:select不只是「多路复用」,time.After、default、done三个搭配才是它在生产环境的真正价值——分别对应「不干等」「不阻塞」「能收场」。
RELATED

相关推荐

Spotlight Attention:优化LLM推理的KV缓存哈希技术

Spotlight Attention:优化LLM推理的KV缓存哈希技术

1. 项目概述 在大型语言模型(LLM)的推理过程中,KV缓存(key-value cache)占据了大量显存资源,成为制约推理效率的关键瓶颈。2025年NIPS会议上提出的Spotlight Attention机制,通过创新的非线性哈希方法重构了KV缓存检索流程,在保持模…

📅 2026/8/22 16:58:09
跨平台演出视频处理:FFmpeg转码与音画同步实战指南

跨平台演出视频处理:FFmpeg转码与音画同步实战指南

在跨平台媒体内容处理和流媒体技术实践中,经常会遇到需要将特定演出或节目从原始格式转换为适应不同播放渠道的版本。这类任务不仅涉及基本的视频转码,还需要考虑音频同步、字幕嵌入、分辨率适配、版权保护等复杂因素。以一场经典演出在不同电视台的播出…

📅 2026/8/22 16:58:10
建筑行业的AI工程进度监控:从无人机影像到进度偏差分析的全链路工程实践

建筑行业的AI工程进度监控:从无人机影像到进度偏差分析的全链路工程实践

建筑行业的AI工程进度监控:从无人机影像到进度偏差分析的全链路工程实践 一、建筑工程进度管理的核心痛点:从人工巡检到自动化监控 建筑工程进度管理是建筑行业最难量化的管理环节。一个10万平米的综合体项目,涉及20余个专业分包,…

📅 2026/9/5 21:59:57
MORE NEWS

更多资讯

📰

STM32CubeMX+FreeRTOS队列实战:从配置到中断安全通信

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

从灾难性遗忘到持续学习:模型可持续更新实战解析

持续学习(Continual Learning)最近两年在AI从业者圈子里被反复提起,但它并不是什么新概念。核心问题其实很朴素:一个已经训练好的模型,在部署之后遇到新任务、新数据,能不能在不彻底重训、不丢失旧知识的前…

📰

土壤湿度传感器原理图解析与STM32 ADC采集标定

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

AI对话系统中的动态记忆机制设计与实现

1. 项目背景与核心挑战在人工智能领域,记忆机制一直是制约系统智能水平的关键瓶颈。传统AI系统往往表现出两种极端:要么完全依赖即时输入做出反应(如简单聊天机器人),要么过度依赖长期训练形成的固定模式(如…

📰

MapReduce深度实践:原理剖析、Shuffle细节与性能调优全攻略

我花了几天时间把 MapReduce 完整过了一遍,一边看源码一边手动搭建环境跑实例,算是把 Hadoop 分布式计算框架这条线彻底理清了。网上讲 MapReduce 的资料很多,但大多偏理论,真正从入门到能独立完成一个任务闭环的笔记不多。这篇分…

📰

CANN HIXL 社区贡献指南:从 Issue 提交、Commit 规范到 PR 合入的完整协作流程

CANN HIXL 社区贡献指南:从 Issue 提交、Commit 规范到 PR 合入的完整协作流程 【免费下载链接】hixl HIXL(Huawei Xfer Library)是一个灵活、高效的昇腾单边通信库,面向集群场景提供简单、可靠、高效的点对点数据传输能力。 项…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬