context 包的主要用途是定义 Context 类型和支持 取消!是的,您没听错;context 包的主要用途是支持取消操作,因为有时为了某种原因,您想要废弃正在做的操作。然而,能提供一些关于您取消决定的额外信息是非常有帮助的。context 包就能让您做到这点!
如果您浏览一下 context 包点源码,就会认识到它的实现是相当的简单——甚至 Context 类型的实现也非常简单,而 context 包是非常重要的。
context 包以前是作为外部 Go 包存在,但在 Go 1.7版本,它第一次作为标准 Go 包出现。因此,如果您有个较老的 Go 版本,再没先下载 context 包前,您不能跟着这节学习。
Context 类型是一个有四个方法的接口,方法名为 Deadline(),Done(),Err(),Value()。好消息是您不需要实现 Context 接口的所有方法——您只需要使用如 context.WithCancel() 和 context.WithTimeout() 函数修改 Context 变量就行。
下面是使用 context 包的示例,用 simpleContext.go 文件源码,分六部分来介绍。
simpleContext.go 的第一部分代码如下:
package main
import (
"context"
"fmt"
"os"
"strconv"
"time"
)
simpleContext.go 的第二部分如下:
func f1(t int) {
c1 := context.Background()
c1, cancel := context.WithCancel(c1)
defer cancel()
go func(){
time.Sleep(4 * time.Second)
cancel()
}()
f1() 函数只需要一个时延参数,因为其他的都定义在函数里了。注意 cancel 变量的类型是 context.CancelFunc。
您需要调用 context.Background() 函数来初始化一个空 Context 参数。context.WithCancel() 函数使用一个存在的 Context 创建一个子类并执行取消操作。context.WithCancel() 函数也会创建一个 Done 通道,如上面的代码所示当 cancel() 函数被调用时,或者当父 context 的 Done 通道关闭时,它会被关闭。
simpleContext.go 的第三部分包含 f1() 函数的其余部分:
这里您看到了 Context 变量的 Done() 函数的使用。当这个函数被调用时,您有一个取消操作。Context.Done() 的返回值是一个通道,否则您就不能在 select 语句中使用它了。
simpleContext.go 的第四部分如下:
这部分展示了 context.WithTimeout() 函数的使用,它需要两个参数:Context 参数和 time.Duration 参数。当超时到达时,cancel() 函数自动调用。
simpleContext.go 的第五部分如下:
上面的代码说明了 context.WithDeadline() 函数的使用,它需要两个参数:Context 变量和一个表示操作将要截止的时间。当期限到了,cancel() 函数自动调用。
simpleContext.go 的最后一段代码如下:
执行 simpleContext.go 产生如下输出:
输出较长的行是 time.After() 函数调用的返回值。它们代表程序正常操作。意味着如果该程序执行超时就会立刻被取消。
这与使用 context 包一样简单,因为介绍的代码没有对 Context 接口做任何重要的工作。不过,下节的 Go 代码将介绍一个更真实的例子。