当前位置:网站首页>Go context 基本介绍
Go context 基本介绍
2022-07-04 09:32:00 【动态一时爽,重构火葬场】
在Go1.7中引入了context,包含goroutine运行状态、环境、现场等信息。并逐渐成为并发控制、超时控制的标准做法。
为什么要有context?
在Go的server中通常每个请求都会启动若干个goroutine同时工作(有的去数据库拿数据,有的调用下游接口获取相关数据)。而这些goroutine需要共享该请求的基本数据,例如登录token、处理请求的最大超时时间等。
因此我们可以将Go server看作一个协程模型。但是这个协程模型在没有context可能会出现一些问题。例如在业务高峰期,下游服务的响应变慢,而当前系统请求没有超时控制,那么等待下游服务的协程便会越来越多,最后导致内存占用飙升,甚至导致服务不可用事故。
对于该事故,其实简单设置一下允许下游最长处理时间就可以避免。而context便非常利于这种设置。
context可以在一组goroutine中传递共享值、取消信息、deadline等。
局部的全局变量
在《代码大全》中指出了全局变量的几大弊端
- 无意中修改
- 命名冲突
- 奇异的别名
- 并发问题
- 初始化顺序无法保证
- 阻碍了代码复用
- 干扰了模块化
个人认为全局变量最严重的问题应该是耦合。其他相对好说
但全局变量却也有着提升数据作用域的好处。
于是很多语言便设计出不那么全局的变量。比如Java中的ThreadLocal,在线程内的全局,避免了线程冲突。再比如Go中的context
对于context而言直接体现这一点就是WithValue,而对于WithTimeout、WithCancel实际上也是全局控制变量
基本使用
主要提供了两种方式创建context
- context.Backgroud():上下文默认值,所有其他的上下文都从他衍生。通常用于main函数、初始化、测试或者顶级上下文
- context.TODO():对于不确定应该使用哪种上下文时使用
两种实际都是type emptyCtx int
实际中还是要通过以下四种With方法进行派生
// WithCancel返回父进程的一个副本,并有一个新的Done channel。当返回的cancel函数被调用或父上下文的Done通道被关闭时,返回上下文的Done通道将被关闭,以哪个先发生为准。
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
// WithDeadline返回父上下文的一个副本,其截止日期调整为不迟于d。如果父上下文的截止日期已经早于d, WithDeadline(parent, d)在语义上等价于parent。
// 当截止日期到期、调用返回的cancel函数或父上下文的Done通道被关闭时,返回上下文的Done通道将被关闭,以先发生的情况为准。
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))
}
// WithValue返回父元素的副本,其中与键关联的值为val。
//上下文值只用于传递进程和api的请求范围内的数据,而不是传递可选参数给函数。
//提供的键必须是可比较的,不应该是string类型或任何其他内置类型,以避免使用context的包之间的冲突。使用WithValue的用户应该定义自己的键类型。在给接口{}赋值时,为了避免分配,上下文键通常有具体的类型struct{}。另外,导出的上下文关键变量的静态类型应该是指针或接口。
func WithValue(parent Context, key, val interface{
}) Context
传递共享数据
常常用于一些“全局变量”。比如说下面代码中发送请求中的reqID,因为之后代码基本上都要用到,因此可以使用context
个人意见其实没必要用context传递共享数据。如果是功能内聚的代码完全可以抽象为结构,将共享数据作为结构。如果传递环节不多,也可以直接传参。如果是“全局”共享的变量,那也可以通过chan或者其他方法共享,当然context也是其他方法中一种。
func TestContextPassValue(t *testing.T) {
handler := withRequestID(http.HandlerFunc(handle))
http.ListenAndServe("/", handler)
}
const reqKey = 0
func withRequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
// fetch request id from header
rid := req.Header.Get("X-Request-ID")
ctx := context.WithValue(req.Context(), reqKey, rid)
req = req.WithContext(ctx)
next.ServeHTTP(rw, req)
})
}
func handle(rw http.ResponseWriter, req *http.Request) {
reqID := req.Context().Value(reqKey)
...
}
取消goroutine
曾有人说context真正解决的问题就是取消。在本文谈到的三种使用,传递共享数据往往有其他甚至更好的方法能做到;防止goroutine泄露,其实也是一种取消goroutine来达到的目的。但是取消下游服务的功能,却只有context能够以最简单的方式去解决。
防止goroutine泄露
假设我们正在一款聊天软件,它拥有实时扫描用户文件夹来保护“安全”的功能。
func imApp() {
close:=make(chan struct{
})
go scanFiles()
select {
case <-close:
return
}
}
func scanFiles() {
// scan user file
}
这个时候用户通知我们将app关闭,那么就可能app其他功能关闭了,可是扫描文件的goroutine一直在运行。
此时为了防止这种情况的出现,可以使用context去防止这种无限运转的goroutine泄露。
func imApp() {
close := make(chan struct{
})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go scanFiles(ctx)
select {
case <-close:
return
}
}
func scanFiles(ctx context.Context) {
select {
case <-ctx.Done():
return
default:
// scan user file partly
}
}
这样最多在取消的时候,扫描了一遍。
慎用context
context虽然非常棒,非常适合写server,尤其对于取消操作。但是如果到处滥用,可能就像病毒一样扩散。并且context实际是链表实现,效率相对来说比较低。
Ref
- https://zhuanlan.zhihu.com/p/68792989
- https://www.cnblogs.com/qcrao-2018/p/11007503.html
- https://www.zhihu.com/question/269905592/answer/364438511
- https://faiface.github.io/post/context-should-go-away-go2/
边栏推荐
- Awk from entry to earth (18) GAW K line manual
- 2022-2028 global optical transparency industry research and trend analysis report
- Report on research and investment prospect prediction of China's electronic grade sulfuric acid industry (2022 Edition)
- Global and Chinese market of planar waveguide optical splitter 2022-2028: Research Report on technology, participants, trends, market size and share
- [on February 11, 2022, the latest and most fully available script library collection of the whole network, a total of 23]
- Four common methods of copying object attributes (summarize the highest efficiency)
- How to display √ 2 on the command line terminal ̅? This is actually a blog's Unicode test article
- Opencv environment construction (I)
- Deadlock in channel
- Global and Chinese market of sampler 2022-2028: Research Report on technology, participants, trends, market size and share
猜你喜欢

165 webmaster online toolbox website source code / hare online tool system v2.2.7 Chinese version

Function comparison between cs5261 and ag9310 demoboard test board | cost advantage of cs5261 replacing ange ag9310

2022-2028 global special starch industry research and trend analysis report

After unplugging the network cable, does the original TCP connection still exist?

【LeetCode 42】501. Mode in binary search tree

2022-2028 global elastic strain sensor industry research and trend analysis report

2022-2028 global gasket metal plate heat exchanger industry research and trend analysis report
![C language - Introduction - Foundation - syntax - [main function, header file] (II)](/img/5a/c6a3c5cd8038d17c5b0ead2ad52764.png)
C language - Introduction - Foundation - syntax - [main function, header file] (II)
](/img/3f/4d8f4c77d9fde5dd3f53ef890ecfa8.png)
C语言-入门-基础-语法-[运算符,类型转换](六)

GoLand environment variable configuration
随机推荐
Investment analysis and future production and marketing demand forecast report of China's paper industry Ⓥ 2022 ~ 2028
Simulate EF dbcontext with MOQ - mocking EF dbcontext with MOQ
Lauchpad x | MODE
ArrayBuffer
Research and investment strategy report of China's electronic hydrogen peroxide industry (2022 Edition)
How to ensure the uniqueness of ID in distributed environment
Launpad | 基础知识
The child container margin top acts on the parent container
26. Delete duplicates in the ordered array (fast and slow pointer de duplication)
How should PMP learning ideas be realized?
Global and Chinese markets of thrombography hemostasis analyzer (TEG) 2022-2028: Research Report on technology, participants, trends, market size and share
C language - Introduction - Foundation - syntax - [identifier, keyword, semicolon, space, comment, input and output] (III)
UML 时序图[通俗易懂]
Global and Chinese market of planar waveguide optical splitter 2022-2028: Research Report on technology, participants, trends, market size and share
Solution to null JSON after serialization in golang
China electronic grade sulfur trioxide Market Forecast and investment strategy report (2022 Edition)
Some points needing attention in PMP learning
Explanation of closures in golang
Launchpad x | mode
[on February 11, 2022, the latest and most fully available script library collection of the whole network, a total of 23]