Go语言Context如何使用
本文最后更新于 2024年10月15日 下午
Go语言Context如何使用
概述
相信大家在日常使用Go语言进行开发的时候一定会遇到下面这种代码,特别是在Web开发中使用了诸如Gin、Echo和Beego类似的开发框架。
1 |
|
能够从上面的代码中看出,每个方法的第一个参数都是Context
。Context
是Go语言在1.7版本引入的,Context
可以用来在goroutine
之间传递上下文信息,通常可以用来进行超时控制,消息传递等,Go语言官方建议的将Context
作为函数的第一个参数并不断地透传下去以实现在不同的goroutine
之间传递上下文。
Context的使用
context
包中提供了两种方式创建Context
:
context.Backgroud()
context.TODO()
通过这两种方式都可以创建一个Context
,而且两者之间没有区别,官方给出的定义是:
context.Background
是上下文的默认值,所有其他的上下文都应该从它衍生(Derived)出来;context.TODO
应该只在不确定应该使用哪种上下文时使用;
使用这两种方法创建出来的Context
都是默认的Context
,也可以称为父Context
,不具备我们上面说到的消息传递,超时控制这些功能,需要实现这些功能就需要使用context
包提供的另外几个创建Context
的方法:
context.WithCancel(parent Context)
context.WithDeadline(parent Context, deadline time.Time)
context.WithTimeout(parent Context, timeout time.Duration)
context.WithValue(parent Context, key, val interface{})
传递数据
在日常的开发中,日志是必不可少的一部分,同时我们都希望在日志打印的时候能够携带一个tranceID
,这样的话根据一个tranceID
就可以关联出一个请求的所有日志,这个在Go语言中就可以使用Context
的传递数据方式实现。
1 |
|
上面的代码中通过WithValue
方法创建了一个可以携带数据的Context
,然后在方法调用链中将Context
作为第一个参数一直传递,在每个方法中都可以通过Value
取到最开始放进去的tranceID
,最后打印结果如下:
1 |
|
超时控制
要使用Context
实现超时控制可以使用WithTimeout
或WithDeadline
,通过这两个方法创建出来的Context
都可以实现超时控制,两个方法的作用是一样的。同时两个方法都会返回一个cancel
方法,通过调用这个方法可以提前取消,不需要等到传入的时间达到即可取消。
示例代码如下:
1 |
|
上面的代码中通过WithTimeout
创建了一个时间为3
秒的Context
,然后在test
方法中进行循环,每隔1
秒输出一个test
语句,但是由于Context
的超时设置的3
秒,所以当3
秒后Context
就会自动取消,最后test
的输出也就只有2行。
1 |
|
WithCancel取消控制
在开发中有时候可能需要同时创建多个goroutine
并行的去进行一些逻辑的处理,但是当主goroutine
出现错误的时候,这时候我们就已经不需要其他的goroutine
继续执行,这种情况我们就可以使用WithCancel
创建一个可以取消的Context
,将Context
传入到不同的goroutine
中,当主goroutine
出错时,直接调用cancel
方法就可以取消所有的goroutine
。
示例代码如下:
1 |
|
上面的代码通过WithCancel
创建了一个可以取消的Context
,然后创建了一个goroutine
执行test
方法,当主goroutine
等待3秒后调用cancel
方法取消,这时候执行test
方法的goroutine
就会直接退出不再执行。
1 |
|