golang context包的使用
go Context
如何在一个goroutine中去通知其他的goroutine退出任务
package main
import (
"context"
"fmt"
"time"
)
func test1(ctx context.Context) {
Block:
for {
select {
case <-ctx.Done():
fmt.Println("test1 over")
break Block
default:
time.Sleep(time.Second * 1)
fmt.Println("test1......")
}
}
}
func test2(ctx context.Context) {
Block:
for {
select {
case <-ctx.Done():
fmt.Println("test2 over")
break Block
default:
time.Sleep(time.Second * 1)
fmt.Println("test2......")
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
go test1(ctx)
go test2(ctx)
time.Sleep(5 * time.Second)
cancel()
time.Sleep(5 * time.Second)
}
WithCancel
:接受一个context参数,返回ctx和一个函数,当函数被调用,ctx的Done
方法将不再阻塞。
package main
import (
"context"
"fmt"
"time"
)
func test1(ctx context.Context) {
Block:
for {
select {
case <-ctx.Done():
fmt.Println("test1 over")
break Block
default:
time.Sleep(time.Second * 1)
fmt.Println("test1......")
}
}
}
func test2(ctx context.Context) {
Block:
for {
select {
case <-ctx.Done():
fmt.Println("test2 over")
break Block
default:
time.Sleep(time.Second * 1)
fmt.Println("test2......")
}
}
}
func main() {
t := time.Now().Add(3 * time.Second)
ctx, cancel := context.WithDeadline(context.Background(), t)
go test1(ctx)
go test2(ctx)
time.Sleep(5 * time.Second)
fmt.Println("main over")
cancel()
}
WithDeadline
:接受一个context参数和一个具体的过期时间点,返回一个context参数和一个函数,当函数主动调用时,ctx的Done
方法将不再阻塞,或者当本地时间大于等于过期的时间点时,ctx
的Done
方法也不再阻塞。
package main
import (
"context"
"fmt"
"time"
)
func test1(ctx context.Context) {
Block:
for {
select {
case <-ctx.Done():
fmt.Println("test1 over")
break Block
default:
time.Sleep(time.Second * 1)
fmt.Println("test1......")
}
}
}
func test2(ctx context.Context) {
Block:
for {
select {
case <-ctx.Done():
fmt.Println("test2 over")
break Block
default:
time.Sleep(time.Second * 1)
fmt.Println("test2......")
}
}
}
func main() {
t := time.Duration(2) * time.Second
ctx, cancel := context.WithTimeout(context.Background(), t)
go test1(ctx)
go test2(ctx)
time.Sleep(5 * time.Second)
fmt.Println("即将结束")
cancel()
fmt.Println("结束")
}
WithTimeout
: 和WithDeadline
一样,它接受的是一个相对时间,到达过期时间点后ctx的Done
不再阻塞, 也可以主动调用cancel
来提前结束
package main
import (
"context"
"fmt"
"time"
)
func test1(ctx context.Context) {
fmt.Println(ctx.Value("key"))
}
func main() {
ctx := context.WithValue(context.Background(), "key", "value")
go test1(ctx)
time.Sleep(1 * time.Second)
}
WithValue
: 可以在Context之间进行值得传递