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

news2024/11/15 2:05:43

作为一个工作8年的老程序员告诉你:阅读源码和查看官方文档,是解决问题最高效的办法。不信你来看,这个困扰了读者半天的问题我查了源码和文档后瞬间解决。

前言

上周五有位读者私信我一个问题,说困扰了他半天,研究了一个上午也没搞明白。

是一位运维转Go的朋友,最近有不少运维、测试、甚至Java、PHP转Go的朋友加我。

这个问题并不是三言两语就能讲清楚的,我就整理了一篇文章给他。

快乐

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

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

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

提问

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

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

先说结论

  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()

再带大家看一下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方法用于设置上下文变量。

使用示例

示例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

一起学习

欢迎关注下方公众号:程序员升职加薪之旅,也欢迎 加我好友 一起学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/357828.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用Rust与Flutter开发一款小工具

1.起因 起因是年前看到了一篇Rust iOS & Android|未入门也能用来造轮子?的文章,作者使用Rust做了个实时查看埋点的工具。其中作者的一段话给了我启发: 无论是 LookinServer 、 Flipper 等 Debug 利器,还是 Flutt…

基于springboot+vue的疾病匿名检测查询系统

基于springbootvue的疾病匿名检测查询系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背…

【拥抱开源】发布自己的项目到maven中央仓库

文章目录🎈第一步,注册账号💿第二步,登录📀第三步,设置信息💾第四步,创建问题📹第五步,验证信息🎥第六步,上传jar包到中央仓库&#x…

网页中字体混淆的处理(简易方法)——爬虫学习笔记

网页中字体混淆的处理——爬虫学习笔记之评论爬取一、网页分析1、打开某点评网址。2、在网页源代码中寻找评论信息(1)进入这个“火锅店”的详情页,然后右击“检查”(2)点上面“刷新”详情页,逐步寻找。&…

RK3288 GPIO记录

1、引脚对应的GPIO 编号第一种 使用/sys/kernel/debug/gpio查询所有gpio引脚的基数第二种 cat /sys/class/gpio/gpiochip248/label对应的label就是GPIO引脚,例如下图GPIO8对应的基数就是2482、计算编号编号 基数 PIN脚如GPIO8的基数是248, GPIO8_A6的编…

Java开发 - 数风流人物,还看“微服务”

目录 前言 服务器端的发展历程 早期的服务器 动态的页面 用户内容网站 微服务 企业级应用 互联网应用 微服务介绍 什么是微服务? 为什么使用微服务 怎么使用微服务 Spring Cloud 什么是Spring Cloud Nacos注册中心 什么是Nacos 创建微服务项目 创建…

【Servlet篇】一文带你吃透Request对象

文章目录1. 前言2. Request 对象2.1 Request 继承体系2.2 Request 获取请求参数1. 获取请求行数据2. 获取请求头数据3. 获取请求体数据4. 获取请求参数的通用方式3. IDEA中快速创建 Servlet你问我青春还剩几年?我的回答是,趁现在,正当时。身边…

CS144-Lab2

实验架构 除了写入传入流之外,TCPReceiver 还负责通知 sender 两件事: “First unassembled” 字节的索引,称为“acknowledgment”或 “ackno”。这是接收方需要来自发送方的第一个字节。“first unassembled ” 索引和“first unacceptable…

【项目精选】基于SSH的任务调度系统的设计与实现(视频+源码+论文)

点击下载源码 虽然科技进步在改革开发这几十年来速度飞快,计算机行业也发展迅速,但仍然有大量商家或企业,甚至项目组,采用落后的人工管理方式或者低效的任务调度策略,这无疑是对计算机的一种无视。 计算机处理信息的准…

Python每日一练(20230220)

目录 1. 存在重复元素 II 2. 按要求实现程序功能 3. 分割链表 附录 链表 1. 存在重复元素 II 给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] nums [j],并且 i 和 j 的差的 绝对值 至多为 k。 …

高级数据类型

为了解决单一的业务而存在bitmapsBitmaps类型的基础操作 获取指定key对应偏移量上的bit值getbit key offset 设置指定key对应偏移量上的bit值,value只能是1或0setbit key offset valueBitmaps类型的扩展操作状态位的统计业务需求:1. 统计每天某一部电…

云计算ACP云服务器ECS实例题库(三)

😘作者简介:一名99年软件运维应届毕业生,正在自学云计算课程。👊宣言:人生就是B(birth)和D(death)之间的C(choise),做好每一个选择。&…

关于监控服务器指标、CPU、内存、警报的一些解决方案

文章目录关于监控服务器指标、CPU、内存、警报的一些解决方案Prometheus Grafana 配置 IRIS / Cach 监控服务器Prometheus简介特点架构图Grafana简介特点配置流程自定义Prometheus接口定义配置 Exporter 监控服务器系统资源简介配置流程使用 Alertmanager报警简介配置流程基于…

软考高级-信息系统管理师之知识管理(最新版)

知识管理 知识与知识管理知识管理常用的方法和工具显性知识的管理隐形知识的管理知识管理的工具学习型组织知识产权保护计算机软件保护条例商标法专利法补充建议学的考点:知识与知识管理 1、知识的分类 知识可分为两类,分别是显性知识与隐性知识。 凡是能以文字与数字来表达…

【C++】关联式容器——map和set的使用

文章目录一、关联式容器二、键值对三、树形结构的关联式容器1.set2.multiset3.map4.multimap四、题目练习一、关联式容器 序列式容器📕:已经接触过STL中的部分容器,比如:vector、list、deque、forward_list(C11)等,这些容器统称为…

新能源汽车,有毒

作者| Mr.K 编辑| Emma来源| 技术领导力(ID:jishulingdaoli)新能源汽车到底有多火,生生逼得奥迪某4S店挂出横幅:我们也有纯电新能源!老牌名车的辛酸憋屈溢出屏幕。网友神评补刀“这标语给人‘诺基亚也有智能大屏机’的感觉。”一…

【Java基础】变量

Java基础 变量 variable 变量类型 实例变量(非静态字段) Instance Variables (Non-Static Fields) 类的非静态属性 类变量(静态字段) Class Variables (Static Fields) 类的静态属性 局部变量 Local Variables 参数 Parameters 变量命名 大小写敏感 开头:字…

爬虫基本知识的认知(爬虫流程 HTTP构建)| 爬虫理论课,附赠三体案例

爬虫是指通过程序自动化地从互联网上获取数据的过程。 基本的爬虫流程可以概括为以下几个步骤: 发送 HTTP 请求:通过 HTTP 协议向指定的 URL 发送请求,获取对应的 HTML 页面。解析 HTML 页面:使用 HTML 解析器对获取的 HTML 页面…

linux shell 入门学习笔记4 shell运维和编程语言

shell 运维和编程语言 脚本注释 shell脚本中,#后面的内容表示注释内容,一般是给开发者或使用者观看,解释器会忽略此部分内容注释可以单独写一行,也可以跟在文件末尾保持注释的习惯,尽量使用英文 例子: #…

C++类和对象(2)构造、析构函数

类的6个默认成员函数 如果一个类中什么成员都没有,简称为空类。 class Date{}; 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员 函数。 默认成员函数:用户没有显式实现&…