当前位置:网站首页>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/
边栏推荐
- ArrayBuffer
- Launpad | Basics
- How to display √ 2 on the command line terminal ̅? This is actually a blog's Unicode test article
- Implementing expired localstorage cache with lazy deletion and scheduled deletion
- C語言-入門-基礎-語法-[運算符,類型轉換](六)
- 26. Delete duplicates in the ordered array (fast and slow pointer de duplication)
- Summary of the most comprehensive CTF web question ideas (updating)
- 2022-2028 global seeder industry research and trend analysis report
- Deadlock in channel
- Awk from entry to earth (14) awk output redirection
猜你喜欢
LeetCode 74. Search 2D matrix
After unplugging the network cable, does the original TCP connection still exist?
PHP book borrowing management system, with complete functions, supports user foreground management and background management, and supports the latest version of PHP 7 x. Database mysql
Mac platform forgets the root password of MySQL
Explain TCP protocol in detail three handshakes and four waves
[untitled] forwarding least square method
At the age of 30, I changed to Hongmeng with a high salary because I did these three things
PHP personal album management system source code, realizes album classification and album grouping, as well as album image management. The database adopts Mysql to realize the login and registration f
Markdown syntax
Ultimate bug finding method - two points
随机推荐
Analysis report on the production and marketing demand and investment forecast of tellurium dioxide in the world and China Ⓣ 2022 ~ 2027
2022-2028 global intelligent interactive tablet industry research and trend analysis report
The old-fashioned synchronized lock optimization will make it clear to you at once!
Investment analysis and future production and marketing demand forecast report of China's paper industry Ⓥ 2022 ~ 2028
Function comparison between cs5261 and ag9310 demoboard test board | cost advantage of cs5261 replacing ange ag9310
Pueue data migration from '0.4.0' to '0.5.0' versions
Review of last week's hot spots (6.27-7.3)
Are there any principal guaranteed financial products in 2022?
Latex download installation record
Awk from entry to earth (14) awk output redirection
Tkinter Huarong Road 4x4 tutorial II
Problems encountered by scan, scanf and scanln in golang
Deadlock in channel
Global and Chinese markets for laser assisted liposuction (LAL) devices 2022-2028: Research Report on technology, participants, trends, market size and share
Report on the development trend and prospect trend of high purity zinc antimonide market in the world and China Ⓕ 2022 ~ 2027
《网络是怎么样连接的》读书笔记 - WEB服务端请求和响应(四)
Global and Chinese markets of water heaters in Saudi Arabia 2022-2028: Research Report on technology, participants, trends, market size and share
HMS core helps baby bus show high-quality children's digital content to global developers
Jianzhi offer 09 realizes queue with two stacks
pcl::fromROSMsg报警告Failed to find match for field ‘intensity‘.