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