golang在context包下提供了一个Context,它可以用来在多个goroutine之间传递信号
1
2
3
4
5
6
7
8
9
10
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
Done方法在context被取消或者工作完成时返回一个close掉的channel,如果context无法被取消,则可能返回一个nil
Deadline 返回context到达指定时间被取消的时间
Background
backGround 不可被取消,没有deadLine
WithCancel
WithCancel返回一个继承的Context,这个Context在父Context的Done被关闭时关闭自己的Done通道,或者在自己被Cancel的时候关闭自己的Done。 WithCancel同时还返回一个取消函数cancel,这个cancel用于取消当前的Context。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func someHandler() {
c := context.Background()
ctx, cancel := context.WithCancel(c)
go doStuff(ctx)
//10秒后取消doStuff
time.Sleep(5 * time.Second)
cancel()
}
//每1秒work一下,同时会判断ctx是否被取消了,如果是就退出
func doStuff(ctx context.Context) {
for {
time.Sleep(1 * time.Second)
select {
case <-ctx.Done():
fmt.Println("done")
return
default:
fmt.Println("work")
}
}
}
func main() {
someHandler()
}
withTimeout
设置超时时间,类似withCancel,只是多了一个超时时间,调用cancel或者达到超时时间context都会被取消
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func someHandler() {
c := context.Background()
ctx, cancel := context.WithTimeout(c, time.Second*3)
go doStuff(ctx)
//10秒后取消doStuff
time.Sleep(5 * time.Second)
cancel()
}
//每1秒work一下,同时会判断ctx是否被取消了,如果是就退出
func doStuff(ctx context.Context) {
for {
time.Sleep(1 * time.Second)
select {
case <-ctx.Done():
fmt.Println("done")
return
default:
fmt.Println("work")
}
}
}
func main() {
someHandler()
}
withDeadline
withDeadline等价于withTimeout,只是讲超时时间改为截止时间
withValue
withValue返回了一个key与value相关联的context
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func someHandler() {
c := context.Background()
ctx := context.WithValue(c, "a", "b")
go doStuff(ctx)
time.Sleep(time.Second)
}
func doStuff(ctx context.Context) {
fmt.Println(ctx.Value("a"))
}
func main() {
someHandler()
}