雅安市政建设公司网站,做电商网站哪家好,云南省建设工程电子网,淘宝官网页版作为一个工作8年的老程序员告诉你#xff1a;阅读源码和查看官方文档#xff0c;是解决问题最高效的办法。不信你来看#xff0c;这个困扰了读者半天的问题我查了源码和文档后瞬间解决。 前言
上周五有位读者私信我一个问题#xff0c;说困扰了他半天#xff0c;研究了一… 作为一个工作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()的源码和注释。
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {return background
}我们可以发现这里返回了一个non-nil, empty Context 问题2. 如何赋值和接收context 在GoFrame框架中官方推荐的正是使用Context上下文对象来处理流程共享的上下文变量甚至将该对象进一步传递到依赖的各个模块方法中。
该Context对象类型实现了标准库的context.Context接口该接口往往会作为模块间调用方法的第一个参数该接口参数也是Golang官方推荐的在模块间传递上下文变量的推荐方式。
方法列表
func (r *Request) GetCtx() context.Context
func (r *Request) SetCtx(ctx context.Context)
func (r *Request) GetCtxVar(key interface{}, def ...interface{}) *gvar.Var
func (r *Request) SetCtxVar(key interface{}, value interface{})简要说明
GetCtx方法用于获取当前的context.Context对象作用同Context方法。SetCtx方法用于设置自定义的context.Context上下文对象。GetCtxVar方法用于获取上下文变量并可给定当该变量不存在时的默认值。SetCtxVar方法用于设置上下文变量。
使用示例
示例1SetCtxVar/GetCtxVar
package mainimport (github.com/gogf/gf/v2/frame/ggithub.com/gogf/gf/v2/net/ghttp
)const (TraceIdName trace-id
)func main() {s : g.Server()s.Group(/, func(group *ghttp.RouterGroup) {group.Middleware(func(r *ghttp.Request) {//向context中赋值r.SetCtxVar(TraceIdName, 1234567890abcd)r.Middleware.Next()})group.ALL(/, func(r *ghttp.Request) {//从context中取值r.Response.Write(r.GetCtxVar(TraceIdName))})})s.SetPort(8199)s.Run()
}可以看到我们可以通过SetCtxVar和GetCtxVar来设置和获取自定义的变量该变量生命周期仅限于当前请求流程。
执行后访问 http://127.0.0.1:8199/ 页面输出内容为1234567890abcd
示例2SetCtx
SetCtx方法常用于中间件中整合一些第三方的组件例如第三方的链路跟踪组件等等。
为简化示例这里我们将上面的例子通过SetCtx方法来改造一下来做演示。
package mainimport (contextgithub.com/gogf/gf/v2/frame/ggithub.com/gogf/gf/v2/net/ghttp
)const (TraceIdName trace-id
)func main() {s : g.Server()s.Group(/, func(group *ghttp.RouterGroup) {group.Middleware(func(r *ghttp.Request) {ctx : context.WithValue(r.Context(), TraceIdName, 1234567890abcd)r.SetCtx(ctx)r.Middleware.Next()})group.ALL(/, func(r *ghttp.Request) {//看到这里的示例代码更能解答问题1通过ghttp.Request可以轻松获得上下文对象r.Response.Write(r.Context().Value(TraceIdName))// 也可以使用// r.Response.Write(r.GetCtxVar(TraceIdName))})})s.SetPort(8199)s.Run()
}执行后访问 http://127.0.0.1:8199/ 页面输出内容为1234567890abcd
总结
通过上面的示例我们能更好的理解这位星友提出的困惑
关于ctx context.Context上下文Server组件会自动从请求中获取并传递给接口方法声明并初始化了context初始值为context.Background()可以通过GetCtx、SetCtx、GetCtxVar、SetCtxVar这些方法轻松的为context赋值和取值通过示例代码轻松可知我们可以通过ghttp.Request实例轻松的操作context。
参考链接 路由注册-规范路由 请求输入-Context
一起学习 欢迎关注下方公众号程序员升职加薪之旅也欢迎 加我好友 一起学习