Go:context包
1. 简介
1.1. 作用
主要用Goroutine管理,停止Goroutine或之间参数传递。
1.2. 核心接口
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
方法 | 说明 |
---|---|
Deadline | 返回截止时间和是否存在截止时间 |
Done | 获取完成chan |
Err | Done关闭的原因,没有关闭返回nil |
Value | 获取上下文中保存的用户值 |
2. 演示
2.1. WithCancel
上下文取消
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 启动工人去干活
go worker(ctx)
time.Sleep(time.Second * 5)
// 告诉工人停止干活
cancel()
time.Sleep(time.Second * 1)
}
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("work over")
return
default:
fmt.Println("at work")
time.Sleep(time.Second * 1)
}
}
}
2.2. WithTimeout
上下文超时
package main
import (
"context"
"encoding/hex"
"fmt"
"io/ioutil"
"net/http"
"time"
)
type Result struct {
r *http.Response
err error
}
func main() {
// 请求超时时间设置为10秒
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
res, err := httpGet(ctx)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(hex.Dump(data))
}
func httpGet(ctx context.Context) (*http.Response, error) {
reqResult := make(chan Result, 1)
go func() {
res, err := http.Get("https://www.baidu.com")
reqResult <- Result{res, err}
}()
select {
case <-ctx.Done():
return nil, ctx.Err()
case result := <-reqResult:
return result.r, nil
}
}
2.3. WithDeadline
上下文截止时间
package main
import (
"fmt"
"golang.org/x/net/context"
"time"
)
func main() {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second * 5))
defer cancel()
select {
case <-time.After(time.Second * 10):
fmt.Println("time.After timeout")
case <-ctx.Done():
// 5秒过后执行,打印:context deadline exceeded
fmt.Println(ctx.Err())
}
}
2.4. WithValue
上下文传参
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx := context.WithValue(context.Background(), "id", 1)
go GetID(ctx)
time.Sleep(1 * time.Second)
}
func GetID(ctx context.Context) {
id, ok := ctx.Value("id").(int)
if ok {
fmt.Println(id)
}
}
2.5. 组合写法
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
defer cancel()
ctx = context.WithValue(ctx, "id", 1)
ctx = context.WithValue(ctx, "name", "yimt1")
// 会覆盖上面值
ctx = context.WithValue(ctx, "name", "yimt2")
if id, ok := ctx.Value("id").(int); ok {
fmt.Println(id)
}
if name, ok := ctx.Value("name").(string); ok {
fmt.Println(name)
}
}