1.值传递
值传递只是context的一个辅助功能,并不是核心功能。一般我们只用context来传递不影响业务主逻辑的可选数据,比如日志信息、调试信息以及元信息等等。
package main
import (
"context"
"fmt"
)
func readContext(ctx context.Context) {
traceId, ok := ctx.Value("key").(string)
if ok {
fmt.Println("readContext key=", traceId)i
} else {
fmt.Println("readContext no key")
}
}
func main() {
ctx := context.Background()
readContext(ctx)
ctx = context.WithValue(ctx, "key", "beautiful")
readContext(ctx)
}
在使用WithValue对ctx包装时,可以设置一个key-value键值对,在goroutine之间传递。
2.超时控制
http请求设置超时时间
package main
import (
"context"
"fmt"
"time"
)
func httpRequest(ctx context.Context) {
for {
// 处理http请求
select {
case <- ctx.Done():
fmt.Println("Request timed out")
return
case <- time.After(time.Second):
fmt.Println("Loading...")
}
}
}
func main() {
fmt.Println("start TestTimeoutContext")
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 3)
defer cancel()
httpRequest(ctx)
time.Sleep(time.Second * 5)
}
//start TestTimeoutContext
//Loading...
//Loading...
//Request timed out
文件io或者网络io等耗时操作,可以查看剩余的时间是否充足,决定是否进行下一步操作
package main
import (
"context"
"fmt"
"time"
)
func copyFile(ctx context.Context) {
deadline, ok := ctx.Deadline()
if ok == false {
return
}
// deadline.Sub(time.Now()) 截止时间与当前时间的差值
isEnough := deadline.Sub(time.Now()) > time.Second * 5
if isEnough {
fmt.Println("copy file")
} else {
fmt.Println("isEnough is false return")
return
}
}
func main() {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second * 4))
defer cancel()
copyFile(ctx)
time.Sleep(time.Second * 5)
}
//isEnough is false return
3.取消控制
goroutine发送取消信号,保证自己这个逻辑中发散出去的goroutine全部成功取消
package main
import (
"context"
"fmt"
"time"
)
func gen(ctx context.Context) <-chan int {
ch := make(chan int)
go func() {
var n int
for {
select {
case ch <- n:
n++
time.Sleep(time.Second)
case <-ctx.Done():
return
}
}
}()
return ch
}
func main() {
// 创建一个Cancel context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
// 达到要求之后触发cancel
cancel()
break
}
}
}
//0
//1
//2
//3
//4
//5
参考资料: