You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言defer、select执行逻辑与context相关用法问题咨询

问题1解答

是的,defer cancel()的执行时机确实在末尾select语句执行结束之后。
Go语言中defer语句的执行规则是:在当前所属函数将要返回前,按defer声明的逆序执行。你这段代码里两个defer都声明在末尾select语句之前,select语句本身是阻塞等待ctx.Done()触发的,只有select拿到返回值执行完对应分支逻辑后,函数才会进入返回前的收尾阶段,此时才会依次执行defer cancel()和defer close(message)。

问题2解答

首先可以明确两个结论:

  1. 这里ctx.Done()永远不会返回nil
  2. 末尾的select语句不会发生永久阻塞

原因如下:

  • 只有根上下文context.Background()、context.TODO()的Done()方法才会返回nil,你代码中的ctx是通过context.WithTimeout()生成的子上下文,这类带取消能力的上下文的Done()方法一定会返回一个真实存在的通道,不会是nil。
  • 这个子上下文的取消逻辑不需要等你手动调用cancel()触发:WithTimeout底层会自动启动定时器,5秒超时时间到了之后,底层会自动调用取消函数关闭Done()通道,此时末尾select中的<-ctx.Done()会立刻返回,select执行结束,之后才会走到defer cancel()的逻辑。
  • 额外补充:context的取消函数是幂等的,就算已经因为超时自动取消过了,后续defer再调用cancel()也不会产生任何副作用,符合Go context的最佳实践要求。

内容的提问来源于stack exchange,提问作者Shin-chan Loves Elephants

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 14:36:04