Golang的context理解
使用方法
context
用于表示一个请求的上下文。一个网络请求,一般开启一个协程处理,而这个协程内部还会开启其它的协程继续处理。为了传递一个请求在不同协程中的处理情况(比如是否超时等),我们利用context
来记录这个情况。同样的,对于一些IO处理,也需要context
保存状态,比如超时时间等。
context
一般用以下两种方式传递:
- 作为函数调用的第一个参数
- 作为一个请求结构体的可选配置
func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error){}
func (r *Request) WithContext(ctx context.Context) *Request
context
应该在程序中流动,而不应该存储,不要直接存储context
在结构体中等。一般来说,一个请求的context
在main
中使用context.BackGorund()
方法生成。一般来说,这个用于控制超时时间。
context
可以继承,一旦一个context
取消了,那么继承自该context
的所有context
都会取消,但是不会影响它的父context
。
context
可以携带一些值,比如:
func WithValue(parent Context, key, val interface{}) Contex
key
必须是可比较的,而且不要是内嵌类型,自定义类型,比如:
一般来说,context
携带的值应该是request-scoped
类型的,即仅仅是本次请求范围内会用到的。像数据库字段之类的,不要在这里写入,因为这是全局都用的。使用context
方式传递数据,会造成函数参数意义不明的情况,给出对比:
// 参数意义不明确
func IsAdminUser(ctx context.Context) bool {x := token.GetToken(ctx)userObject := auth.AuthenticateToken(x)return userObject.IsAdmin() || userObject.IsRoot()
}// 明确参数的意义,这是合理的方式
func IsAdminUser(token string, authService AuthService) int {userObject := authService.AuthenticateToken(token)return userObject.IsAdmin() || userObject.IsRoot()
}
但是,有些情况下,可以简化API的设计。比如我们有一个较长的函数调用链,向userId
这种数据,却要从头到尾传递整个调用链,这不是一个好的方法。我们此时可以把这些数据封装到context
中。这些数据不能是控制类型的字段,即传入函数的执行结果,最好不要依赖这些值;但是log
等函数,可以打印这些数据,因为这部影响函数执行结果。
一般不建议使用context.Value
的模式,这在后期重构等时候,造成一些不好的影响,除非必要,否则勿用。
使用原则和技巧:
- 不要把Context放在结构体中,要以参数的方式传递,parent Context一般为Background
- 应该要把Context作为第一个参数传递给入口请求和出口请求链路上的每一个函数,放在第一位,变量名建议都统一,如ctx。
- 给一个函数方法传递Context的时候,不要传递nil,否则在tarce追踪的时候,就会断了连接
- Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递
- Context是线程安全的,可以放心的在多个goroutine中传递
- 可以把一个 Context 对象传递给任意个数的 gorotuine,对它执行取消操作时,所有 goroutine 都会接收到取消信号。
参考资料:
- https://blog.golang.org/context
- https://juejin.im/post/5a6873fef265da3e317e55b6
- https://www.ardanlabs.com/blog/2019/09/context-package-semantics-in-go.html
- http://p.agnihotry.com/post/understanding_the_context_package_in_golang/
- https://medium.com/@cep21/how-to-correctly-use-context-context-in-go-1-7-8f2c0fafdf39
Golang的context理解相关推荐
- 深入理解Golang之context
深入理解Golang之context context是Go并发编程中常用到一种编程模式.本文将从为什么需要context,深入了解context的实现原理,以了解如何使用context. 作者:Tur ...
- golang 上下文 Context
上下文 context.Context Go 语言中用来设置截止日期.同步信号,传递请求相关值的结构体.上下文与 Goroutine 有比较密切的关系,是 Go 语言中独特的设计,在其他编程语言中我们 ...
- golang:context介绍
我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战 1 前言 最近实现系统的分布式日志与事务管理时,在寻求所谓的全局唯一Goroutine ID无果之后,决定还是简单利用Conte ...
- 深入解析Golang之Context
context是什么 context翻译成中文就是上下文,在软件开发环境中,是指接口之间或函数调用之间,除了传递业务参数之外的额外信息,像在微服务环境中,传递追踪信息traceID, 请求接收和返回 ...
- Golang中context实现原理剖析
转载: Go 并发控制context实现原理剖析 1. 前言 Golang context是Golang应用开发常用的并发控制技术,它与WaitGroup最大的不同点是context对于派生gorou ...
- Golang 之context用法
文章目录 1. context 2. context.go 2.0 结构图 2.1 Context interface 2.2 emptyCtx 2.3 cancelCtx 2.4 valueCtx ...
- Android中的Context理解
1.sdk当中关于Context的介绍 Interface to global information about an application environment. This is an abs ...
- 【GoLang】深入理解slice len cap什么算法? 参数传递有啥蹊跷?
先上结论 1.内置append函数在现有数组的长度 < 1024 时 cap 增长是翻倍的,再往上的增长率则是 1.25,至于为何后面会说. 2.Go语言中channel,slice,map这三 ...
- golang库context学习
context库 context最早的背景说明还是来源于官方的 博客,说明如下: 在Go服务器中,每个传入请求都在其自己的goroutine中进行处理. 请求处理程序通常会启动其他goroutine来 ...
最新文章
- 陌陌财报双双超预期,什么才是它的基本盘?
- 【图像超分辨率】遥感数据的高斯金字塔尺度上推方法研究
- CenOS 配置C/C++语言
- cisco 双ISP线路接入,链路自动切换方案
- 【SQL】找出行数与自增标识值不相等的表(即有缺行)
- Intellij IDEA 配置
- USB 3.1 与 Type-C 接口有什么关系呢
- 为Windows添加日志事件
- 人工智能为什么不用C语言,Ai人工智能和C语言差不多吗
- 【Window】英文系统显示中文乱码
- 小米max2装鸿蒙,小米Max2最全评测 小米Max2值不值得买?
- 电量统计(1)-原理
- php 货币换算,PHP货币换算程序代码
- “非功能需求”属于模糊术语吗
- 芒果超媒前三季营收102亿:同比降12% 互联网广告收入降26%
- Warning: Accessing non-existent property ‘cd‘ of module exports inside circular dependency
- 为什么美国大城市里不修二环三环四环五环?
- 揭开人创造思维之谜:浴缸和床最易引发灵感
- 力扣121题 “买卖股票的最 佳时机”
- linux- 日志管理