Go:context包

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
ErrDone关闭的原因,没有关闭返回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)
	}
}
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页