「读源码」为什么注册路由时没有传入上下文,在接口方法中却能取到?

作为一个工作 8 年的老程序员告诉你:阅读源码和查看官方文档,是解决问题最高效的办法。不信你来看,这个困扰了读者半天的问题我查了源码和文档后瞬间解决。
前言
上周五有位读者私信我一个问题,说困扰了他半天,研究了一个上午也没搞明白。
是一位运维转 Go 的朋友,最近有不少运维、测试、甚至 Java、PHP 转 Go 的朋友加我。
这个问题并不是三言两语就能讲清楚的,我就整理了一篇文章给他。
快乐

正如上图所示,反馈特别的好,更文的快乐又找到了,我把这个问题和解答又好好整理了一下,分享给大家,希望对大家有帮助.
也分享一下我作为一个工作 8 年的老程,解决问题的心得:
阅读源码和查看官方文档,是解决问题最高效的办法。
提问
在 gofame 框架的 demo 案例中,如下图所示:

为什么左侧路由绑定这里没有向 controller 中传入 context 的值,在 controller 中却能取到值?
如何赋值和接收 context?
先说结论

关于
ctx context.Context
上下文,Server 组件会自动从请求中获取并传递给接口方法,声明并初始化了 context 初始值为context.Background()
可以通过 GetCtx、SetCtx、GetCtxVar、SetCtxVar 这些方法轻松的为 context 赋值和取值
通过示例代码轻松可知:我们可以通过
ghttp.Request
实例轻松的操作 context。
解答
问题 1. 为什么左侧路由绑定这里没有向 controller 中传入 context 的值,在 controller 中却能取到值?
先说结论:关于ctx context.Context
上下文,Server 组件会自动从请求中获取并传递给接口方法。
关键代码是上图中的s := g.Server()
:
追踪一下它的源码可以发现:声明并初始化了 ctx 的初始值:context.Background()

再带大家看一下context.Background()
的源码和注释。
我们可以发现这里返回了一个non-nil, empty Context

问题 2. 如何赋值和接收 context?
在 GoFrame 框架中,官方推荐的正是使用 Context 上下文对象来处理流程共享的上下文变量,甚至将该对象进一步传递到依赖的各个模块方法中。
该 Context 对象类型实现了标准库的 context.Context 接口,该接口往往会作为模块间调用方法的第一个参数,该接口参数也是 Golang 官方推荐的在模块间传递上下文变量的推荐方式。
方法列表:
简要说明:
GetCtx 方法用于获取当前的 context.Context 对象,作用同 Context 方法。
SetCtx 方法用于设置自定义的 context.Context 上下文对象。
GetCtxVar 方法用于获取上下文变量,并可给定当该变量不存在时的默认值。
SetCtxVar 方法用于设置上下文变量。
使用示例
示例 1,SetCtxVar/GetCtxVar
可以看到:我们可以通过 SetCtxVar 和 GetCtxVar 来设置和获取自定义的变量,该变量生命周期仅限于当前请求流程。
执行后,访问 http://127.0.0.1:8199/ ,页面输出内容为:1234567890abcd
示例 2,SetCtx
SetCtx 方法常用于中间件中整合一些第三方的组件,例如第三方的链路跟踪组件等等。
为简化示例,这里我们将上面的例子通过 SetCtx 方法来改造一下来做演示。
执行后,访问 http://127.0.0.1:8199/ ,页面输出内容为:1234567890abcd
总结
通过上面的示例,我们能更好的理解这位星友提出的困惑:
关于
ctx context.Context
上下文,Server 组件会自动从请求中获取并传递给接口方法,声明并初始化了 context 初始值为context.Background()
可以通过 GetCtx、SetCtx、GetCtxVar、SetCtxVar 这些方法轻松的为 context 赋值和取值
通过示例代码轻松可知:我们可以通过
ghttp.Request
实例轻松的操作 context。
参考链接
一起学习
可以通过下方作者栏的信息联系我,一起学习进步。
版权声明: 本文为 InfoQ 作者【王中阳Go】的原创文章。
原文链接:【http://xie.infoq.cn/article/53731926b4d064593d553bc03】。文章转载请联系作者。
评论 (1 条评论)