更文的快乐又体会到了 解决了困扰读者半天的问题

简介: 更文的快乐又体会到了 解决了困扰读者半天的问题

快乐

image.png

正如上图所示,反馈特别的好,更文的快乐又找到了,我把这个问题和解答又好好整理了一下,分享给大家,希望对大家有帮助.

也分享一下我作为一个工作8年的老程,解决问题的心得:

阅读源码和查看官方文档,是解决问题最高效的办法。

提问

在gofame框架的demo案例中,如下图所示:

image.png

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

先说结论

image.png

  1. 关于ctx context.Context上下文,Server组件会自动从请求中获取并传递给接口方法,声明并初始化了context初始值为context.Background()
  2. 可以通过GetCtx、SetCtx、GetCtxVar、SetCtxVar这些方法轻松的为context赋值和取值
  3. 通过示例代码轻松可知:我们可以通过ghttp.Request实例轻松的操作context。

解答

问题1. 为什么左侧路由绑定这里没有向controller中传入context的值,在controller中却能取到值?

先说结论:关于ctx context.Context上下文,Server组件会自动从请求中获取并传递给接口方法。

关键代码是上图中的s := g.Server():

追踪一下它的源码可以发现:声明并初始化了ctx的初始值:context.Background()

f3ff3187a706d0f7beee2200ba6a093.png

再带大家看一下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

image.png

问题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方法用于设置上下文变量。

使用示例

示例1,SetCtxVar/GetCtxVar

package main
import (
  "github.com/gogf/gf/v2/frame/g"
  "github.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

示例2,SetCtx

SetCtx方法常用于中间件中整合一些第三方的组件,例如第三方的链路跟踪组件等等。

为简化示例,这里我们将上面的例子通过SetCtx方法来改造一下来做演示。

package main
import (
  "context"
  "github.com/gogf/gf/v2/frame/g"
  "github.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

总结

通过上面的示例,我们能更好的理解这位星友提出的困惑:

  1. 关于ctx context.Context上下文,Server组件会自动从请求中获取并传递给接口方法,声明并初始化了context初始值为context.Background()
  2. 可以通过GetCtx、SetCtx、GetCtxVar、SetCtxVar这些方法轻松的为context赋值和取值
  3. 通过示例代码轻松可知:我们可以通过ghttp.Request实例轻松的操作context。

参考链接

路由注册-规范路由、请求输入-Context


微信号:wangzhongyang1993  公众号:程序员升职加薪之旅  B站视频:王中阳Go

相关文章
|
1月前
|
算法 JavaScript 前端开发
探索编程之美:从小白到大牛的旅程
【10月更文挑战第9天】编程,这个听起来高深莫测的词汇,实际上就像是一场奇妙的探险。它不仅仅是冷冰冰的代码和算法,更是一扇打开新世界大门的钥匙。本文将带你领略编程的魅力所在,从最初的迷茫与困惑,到逐渐找到自己的方向,最终在技术的海洋里遨游。无论你是编程新手,还是希望进一步提升的开发者,都能在这段旅程中找到属于自己的光芒。
|
3月前
|
算法
技术感悟:编程之路上的点滴收获
【8月更文挑战第19天】在编程的世界里,我如同一名探险家,不断探索、发现和创造。从最初的迷茫到现在的游刃有余,我经历了许多挑战和困难,也收获了许多宝贵的经验和感悟。本文将分享我在编程之路上的点滴收获,希望能给同样热爱编程的你带来一些启示和鼓励。
39 0
|
小程序 测试技术
【技巧】软件测试的面试这些技巧记得不要错过了
拥有一个心仪的offer,是每个软件测试工程师们都梦寐以求的事情,那如何才能通过最后的面试一关,拿到offer呢? 俗话说,知己知彼百战不殆,作为测试员,在面试前对面试官可能提出的问题进行总结和准备,是帮助我们取得好成绩的最佳方式,所以,这些有关软件测试的面试技巧记得不要错过了!
152 0
感想与体会
文中讲述本人学习网页制作的经历、感想与体会
183 0
|
SQL 算法 NoSQL
编写代码最应该做好的事情是什么?(备战2022春招或暑期实习,每天进步一点点,打卡100天,Day8)
编写代码最应该做好的事情是什么?(备战2022春招或暑期实习,每天进步一点点,打卡100天,Day8)
149 0
编写代码最应该做好的事情是什么?(备战2022春招或暑期实习,每天进步一点点,打卡100天,Day8)
快速背诵的心得体会
快速背诵的心得体会
128 0
快速背诵的心得体会
|
前端开发 Java 程序员
程序员:写作能收获什么?
很多程序员已经通过自己的个人博客或者公众号来进行技术沉淀,记录自己的成长。越来越多的程序员们也开始意识到了写作的重要性。程序员为什么需要写作?写作能带来什么收获?又有哪些额外的惊喜?本文介绍三位长期坚持写作的程序员,分享他们在写作道路上的心得和收获,希望对同学们有所启发。
3047 0
程序员:写作能收获什么?
关于“收获”啰嗦几句。
  桌子上有一水杯,杯子里有半杯水。   甲看到了说:太好了,还有半杯水。   乙看到了说:只有半杯水了。   从另一个角度说,甲关注的是“水”,而乙关注的是“空气”即水面到杯子口的那段空间。
631 0
下一篇
无影云桌面