-
我在 Go 的 for-select 循环里用 time.After 做超时、自以为简洁标准,结果服务跑久了内存一路缓慢上涨、profile 一看堆里全是没释放的定时器,最后才搞懂 time.After 每次求值都新建一个定时器而它要等到到期那一刻才会被回收的深度复盘
我有个后台 goroutine 在 for 循环里用 select 处理一个高频消息 channel,同时想加一个多久没消息就做点别的的超时,很自然写成 case- 6
- 0
-
我的 AI Agent 多步任务跑着跑着就再也不动了、既不报错也不返回结果,用户那边一直转圈等到天荒地老,我盯着日志看了半天发现它卡在某一次调用外部工具的地方一动不动,最后才意识到我给每个工具调用都没设超时一个外部接口不返回就能让整个 Agent 永远等下去的深度复盘
我的 Agent 编排了一串步骤:理解任务→调工具A查数据→调工具B处理→调工具C生成结果→返回,每个工具调用都是调用→同步等返回→拿结果进下一步,平时跑得好好的。可某天它处理一个任务时卡住了:没有任何报错、没有任何结果、进度停在中间,用户界面一直转圈。我看日志,执行轨迹停在正在调用工具B这一行后面再无输出,以为是内部死循环(没有)、以为崩溃了(进程还活着就是不动),直到去查工具B对应的外部接口才…- 0
- 0
-
我的 Go 程序某个功能莫名其妙地卡住、既不报错也不返回,goroutine 越积越多最后内存涨爆,排查半天才发现是一个 channel 忘了 make 初始化、它是 nil,而往 nil channel 收发竟然不是报错、而是永久阻塞的深度复盘
我有段 Go 代码用 channel 在 goroutine 间传数据,在结构体里声明了一个 channel 字段,启动 goroutine 往里发另一边收,自测小场景跑通了。可某功能上线后行为诡异:它莫名卡住——既不报错也不返回也不超时,就静静挂着;随请求进来卡住的 goroutine 越积越多内存一路涨爆。我以为是死锁、下游慢,查半天没问题。直到打 goroutine 栈,发现一大堆都阻塞在那…- 0
- 0
-
我的 HTTP 请求明明已经超时返回了,可它在后台启动的 goroutine 还在埋头跑、下游调用也没停,goroutine 越积越多内存一路涨,因为我没把 context 的取消信号传下去也没人监听它的深度复盘
我有个接口处理请求时会启动一些 goroutine 做并行子任务,并给请求设了超时。线上现象诡异:有些请求超时返回了,可监控显示 goroutine 数量只增不减、内存一路缓慢上涨。排查发现那些超时的请求主流程返回了,但它启动的 goroutine 还在后台埋头跑(还在查早已没人要结果的下游)、跑完没人收、白白耗着然后泄漏。复盘才搞懂:Go 用 context 传播取消/超时,请求超时时 ctx …- 5
- 0
-
我给 AI Agent 写了个查数据库的工具,某次它查出了几万行结果原封不动塞进了对话上下文,当场超出 token 上限报错,就算没报错模型也被海量数据淹没得抓不住重点:一次工具返回过大塞爆上下文的深度复盘
我做了个 AI Agent,配了个 query_database(sql) 工具让它查业务数据。平时挺好用,直到某次用户问把所有订单列出来分析一下,Agent 生成了个没加 LIMIT 的查询,工具查出几万行、我原封不动拼成字符串塞回上下文,当场 context length exceeded 报错、对话崩了。我截断到不超限后问题依旧:模型被几千行原始数据淹没、抓不住重点、又慢又贵又含糊。复盘才想…- 0
- 0
-
一个每次请求都起一个 goroutine 却没人保证它能退出的服务,goroutine 越积越多、内存缓慢上涨,跑几天就 OOM:一次 goroutine 泄漏的深度复盘
服务内存缓慢上涨、跑几天就被 OOM,pprof 一看 goroutine 从几十个涨到几十万、只增不减,且全卡在同一行 channel 接收/发送上。根因是每请求起 goroutine 通过无缓冲 channel 返回结果,而主流程超时/取消后提前返回、不再接收,那个负责发送的 goroutine 就永远阻塞在 ch- 0
- 0
-
服务跑了几天,goroutine 数量涨到了几十万,内存也跟着爆了:我写的 goroutine 悄悄地泄漏了的那次排查复盘
Go 服务跑几天就内存越涨越高、最后崩溃,重启又能撑几天。pprof 一查,活跃 goroutine 竟有几十万个,绝大多数都卡在同一行 channel 发送上。根因是 goroutine 泄漏:我为每个查询起一个 goroutine 往无缓冲 channel 发结果,但主函数只接收一次拿最快的就 return 了,其余 goroutine 因为没人接收、永远阻塞在发送上、退不出去。这篇从 gor…- 0
- 0
-
内存慢性漏气定期 OOM:Go 协程泄漏避坑复盘
这是一个让我和运维被半夜告警折磨了快一周的事故:一个 Go 写的后端服务上线后一切正常,可跑上两三天内存就会悄悄爬到上限,然后被 OOM 杀掉自动重启,重启后归零又开始新一轮缓慢爬升,周而复始。它不是一上线就崩的急性病,而是跑着跑着就虚了的慢性病,每隔两三天准时 OOM 一次,最折磨人的是 QPS 没涨流量很平稳,内存却像漏气的轮胎只进不出。真正破案靠的是 Go 自带的神器 pprof:把 gor…- 0
- 0
-
内存只涨不降、几万协程卡死:Go goroutine 泄漏避坑
有个 Go 后台服务跑了几周后运维找上门:进程内存像吹气球一样一天涨一点、从不回落,最后逼近上限被 OOM 杀掉,重启再涨周而复始。我先按内存泄漏的老套路查对象没揪出元凶,直到顺手看了眼 runtime.NumGoroutine 返回的协程数量当场倒吸一口凉气:这个数字也在只涨不降,从启动时几十个涨到几万个还在稳步往上爬。真相浮出水面——不是对象泄漏,是 goroutine 泄漏:每处理一个请求代…- 3
- 0
-
从一套裸起 goroutine 不管生命周期加无缓冲 channel 发送方阻塞下游一慢就泄漏到 OOM 加全局 map 当缓存被多 goroutine 无锁并发读写高并发下 concurrent map fatal 崩进程加到处 if err != nil 直接 return 把错误上下文丢得一干二净加压根不传 context 超时不可控取消不传播加靠 interface{} 加类型断言硬凑运行时 panic 加用 GOPATH 加手动 vendor 锁不住依赖加靠 fmt.Println 调试的早期 Go 祖传微服务、核心是支撑公司订单聚合与支付回调的微服务功能上一直能用在并发量不大的那些年里默默聚合订单接收支付回调直到一次大促把并发推高一个数量级这套从骨子里就没认真对待过 goroutine 生命周期和并发安全的代码在最不该出事的那一夜集中爆炸、把我们打醒的是大促当晚的连环崩溃第一记重拳来自那些没人管死活的 goroutine 网关给每个请求裸起一个 goroutine 去并发调下游再用无缓冲 channel 把结果收回来可一旦下游变慢上游请求因超时提前 return 走了那个还在傻等着往无缓冲 channel 里发结果的 goroutine 就因为再也没有接收方而永远阻塞在那条发送语句上再也退不出去大促那晚下游一变慢这种泄漏的 goroutine 开始成千上万地堆积每个都死死攥着自己那份请求上下文和缓冲区不放内存一路飙升最终 OOM 进程被杀几乎同时第二记重拳砸下另一处用一个全局 map 当本地缓存好几个 goroutine 并发地读它写它却没有加任何锁大促高并发下并发的读和写终于真正撞在一起 Go runtime 检测到 concurrent map read and map write 直接抛出一个连 recover 都救不回来的 fatal error 把整个进程当场干掉 → 2026 现代 Go 工程体系 context 控制生命周期加超时取消加 errgroup 编排 goroutine 启动即规划退出 + RWMutex 加 sync.Map 保护并发安全加 go test -race 检测竞态写代码时就被揪出 + fmt.Errorf 的 %w 包装错误链加 errors.Is/As 精确判断错误带完整来龙去脉 + context.Context 贯穿调用链超时与取消沿链传播一处慢则一起及时放手 + generics 类型参数编译期类型安全一份逻辑适配多类型无运行时断言 + 规范 defer 紧跟获取显式生命周期循环内资源即时释放绝不泄漏句柄 + Go Modules 加 go.mod go.sum 锁定整棵依赖树任何机器拉出完全一致的版本 + slog 结构化日志分级别带字段可检索聚合告警 87 天战役复盘:8 个 P0 复盘 + 6 条工程哲学 + 7 个关键数字
5 人的后端团队 87 天把一套支撑公司订单聚合与支付回调的核心 Go 微服务,从一堆裸起 goroutine 不管生命周期、用全局 map 当缓存却不加锁、到处 if err != nil 直接 return 把错误上下文丢光、压根不传 context、靠 interface{} 加类型断言硬凑、用 GOPATH 加手动 vendor 锁不住依赖、靠 fmt.Println 调试的早期 Go 代…- 7
- 0
-
从粗放 Go 微服务裸 go 无限开 goroutine 泄漏暴涨几十万 OOM + 无 context 传递被慢下游拖垮全链路无限干等堆积雪崩 + err 被 _ 丢掉漏接出错不知哪层报的 + 滥用 panic 当错误处理没 recover 一个边角崩整个进程 + 共享变量裸读写 data race 偶发脏数据和 concurrent map writes 崩溃 + interface{} 加类型断言丢类型安全运行时动不动 panic + 手撸 WaitGroup 加 error channel 协调并发又长又易错死锁漏收 + 热点频繁分配小对象 GC 压力大 STW 停顿肉眼可见 + 线上黑盒哪慢哪漏全靠猜 + 部署直接 kill 硬断在途请求连接 → 2026 现代高并发 Go 工程 worker pool 受控并发加 context 退出 + context 全链路传递超时取消 + 显式 error 加 %w wrapping 加 errors.Is/As + Mutex/atomic/channel 保护加 -race 检测 + 泛型 type-safe 编译期保证 + errgroup 统一并发错误取消 + sync.Pool 复用减少逃逸 + pprof/trace/metrics 可观测 + signal 加 context 优雅关闭 drain 排空 87 天战役复盘:47 套工程修法 + 7 个 P0 复盘 + 6 条工程哲学
10 人的 Go 基础设施与后端团队 87 天把一套用了四年、流量从每秒几千涨到每秒几十万后种种粗放并发写法集中爆雷的 Go 微服务集群——到处是裸 go 启动 goroutine 不加任何数量限制也没有退出机制高峰期 goroutine 暴涨到几十万 OOM、很多 goroutine 因为在阻塞 channel 上永远等不到信号而悄无声息泄漏越积越多、请求链路上完全没有 context 传递一个…- 4
- 0
-
从 Go 1.x GOPATH 时代 + dep/手工 vendor 依赖对不上 + 无泛型到处 interface{} 断言 + 裸 errors.New 拼字符串无上下文 + 不传 context 协程无法取消超时 + 满世界 sync.Mutex 加锁易死锁 + 手撸 goroutine 不管生命周期到处泄漏 + 标准 log 无结构 古老 Go 体系 → 2026 Go 1.22 + Go Modules 可复现依赖 + 泛型类型安全 + errors.Is/As 错误包装错误链 + context 全链路传递取消超时 + channel/errgroup 并发编排 + slog 结构化日志 + 泛型容器函数式工具 现代 Go 体系 87 天战役复盘:47 套工程修法 + 7 个 P0 复盘 + 6 条工程哲学
13 位 Go 后端工程师 87 天把一套跑了六年的古老 Go 体系——GOPATH 目录束缚、dep 和手工 vendor 管依赖经常对不上、完全没有泛型到处 interface{} 加类型断言、裸 errors.New 拼字符串没堆栈没上下文、不传 context 协程无法取消无法超时、满世界 sync.Mutex 共享内存加锁还经常死锁、手撸 goroutine 不管生命周期到处泄漏、标准 …- 6
- 0
-
Go context 用 Background 启动后台 goroutine 拖死 PG 连接池的 3 天复盘:1800 个僵尸 goroutine 实战定位 + WithoutCancel 正解
一个 Go 订单聚合服务在 QPS 1200 时数据库连接池被打到 95%,根因是为了让审计归档任务跑完, 同事在异步 goroutine 里把 ctx 替换成了 context.Background, 加上同步 SDK 偶发卡死, 导致 PG 连接被 1800 个僵尸 goroutine 持续 hold。本文复盘 3 天定位过程, 讲清楚 pprof 排查、context 传播机制、contex…- 0
- 0
-
gRPC 全链路 deadline 传播实战:从下游被卡死到 5 分钟定位
A→B→C→D 链路客户端早超时退出,D 还在傻乎乎跑 30 秒,DB 连接池打满。本文讲透 gRPC deadline 自动传播机制 + Context 取消 + Java/Go 实现 + 客户端服务端拦截器 + 重试配合 + DB 层传 timeout。附完整代码 + 监控告警 + 团队规范。- 0
- 0
Context
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!














