协程无限循环或同步阻塞(如time.sleep)会卡死python asyncio事件循环,导致服务完全无响应;go中未绑定context的goroutine易泄漏,造成内存持续增长。

协程无限循环卡死事件循环
Python 的 asyncio 事件循环是单线程协作式调度,一旦某个协程陷入纯 CPU 计算且不 await,整个服务就失去响应——HTTP 请求不处理、定时任务不触发、健康检查超时。这不是“慢”,而是彻底冻结。
- 典型场景:在协程里写
while True:做轮询,或用time.sleep()替代asyncio.sleep() -
time.sleep()是同步阻塞调用,会卡住整个事件循环;必须改用await asyncio.sleep(1) - CPU 密集型逻辑(如解析大 JSON、加密计算)不能直接在协程中执行,得用
loop.run_in_executor(None, cpu_bound_func)搬到线程池
Go 中 goroutine 泄漏导致内存持续增长
从 Python Web(如 FastAPI + Uvicorn)转 Go(如 Gin + goroutine)时,容易把“启一个后台任务”的惯性带到 Go,但 Go 没有自动回收机制——goroutine 一旦启动,除非自己退出或被 context 取消,否则永远驻留。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 常见泄漏点:HTTP handler 中启 goroutine 处理耗时逻辑,但没绑定
req.Context(),请求中断后 goroutine 还在跑 - 错误写法:
go doSomething();正确写法:go func() { - 用
pprof定期看/debug/pprof/goroutine?debug=2,发现数量持续上涨就是泄漏信号
Python 协程的“伪并行” vs Go goroutine 的“真并行”误判
开发者常以为“都叫协程,行为应该差不多”,结果在 Go 里照搬 Python 的并发模型,引发资源失控。
- Python 协程默认只用 1 个 OS 线程,
asyncio.gather()是并发(concurrent),不是并行(parallel);Go 的 goroutine 默认可跨多核并行执行 - 后果:Python 里开 1000 个协程很安全;Go 里直接
for i := 0; i 可能瞬间创建上千 goroutine,吃光内存或触发系统级文件描述符限制 - 必须加限流:用
semaphore(如golang.org/x/sync/semaphore)或带缓冲 channel 控制最大并发数
上下文取消传播不完整
Python 的 asyncio.CancelledError 在 await 点自动抛出,而 Go 的 context.Context 需要显式检查 ctx.Err() != nil,漏掉一处就导致 goroutine 悬停。
- 尤其在嵌套调用链中:A → B → C,如果 C 忘了检查
ctx,A 调用ctx.Cancel()后,C 仍继续执行 - 数据库查询、HTTP client、time.Timer 都支持
context,优先用db.QueryContext(ctx, ...)而非db.Query(...) - 自定义 long-running loop 必须在每次迭代开头加
select { case 或直接 <code>if ctx.Err() != nil { return }
await 是语法硬要求),在 Go 是工程自觉(靠人写 select / ctx.Done() / runtime.Gosched())。前者不易错,后者极易漏——这也是从 Python 转 Go 最容易栽跟头的地方。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










