张 永 一个梦想自由的程序员

——————————————— 让科技和智能使人更便捷 ———————————————
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

go context 梳理

Posted on 2022-02-10 20:47  hylas  阅读(101)  评论(0编辑  收藏  举报

context 是go的基础包

context 的使用场景:1. 控制关闭goruntine , 防止溢出  2. 定时完成goruntine  3. 带参数给 goruntine 

对应的有以下几种 context :

context.WithCancel
context.WithDeadline
context.WithTimeout
context.WithValue

 

context.Background() 用来 new 一个新 context
context.TODO()  用来 new 一个context 备用


类关系:

 

源码解析:
查看 go 源码或 看 http://www.codebaoku.com/godeep/goddeep-context-src.html

使用参照:
cancel:

gen := func(ctx context.Context) chan int {
		dst := make(chan int)
		n := 1
		go func() {
			fmt.Println("new go ")
			for {
				select {
				case <-ctx.Done():
					fmt.Println("goroutine over")
					return // return结束该goroutine,防止泄露
				case dst <- n:
					n++
				}
			}
		}()
		return dst
	}
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // 当我们取完需要的整数后调用cancel
	for n := range gen(ctx) {
		fmt.Println(n)
		if n == 5 {
			break
		}
	}

 

deadline / timeout

	d := time.Now().Add(50 * time.Millisecond)
	ctx, _ := context.WithDeadline(context.Background(), d)
	// ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
	// 尽管ctx会过期,但在任何情况下调用它的cancel函数都是很好的实践。
	// 如果不这样做,可能会使上下文及其父类存活的时间超过必要的时间。
	// defer cancel() 如果调用, 是主动停止(canceled) goruntine; 如果不调用 则是超时出 deadline exceeded
	go func() {
		select {
		case <-time.After(1 * time.Second):
			fmt.Println("sleep ")
		case <-ctx.Done():
			fmt.Println(ctx.Err())
			fmt.Println("over")
			return

		}
	}()

	time.Sleep(time.Second * 5)

  
contextval

	type favContextKey string // 定义一个key类型
	// f:一个从上下文中根据key取value的函数
	f := func(ctx context.Context, k favContextKey) {
		if v := ctx.Value(k); v != nil {
			fmt.Println("found value:", v)
			return
		}
		fmt.Println("key not found:", k)
	}
	k := favContextKey("language")
	// 创建一个携带key为k,value为"Go"的上下文
	// context.TODO()
	ctx := context.WithValue(context.Background(), k, "Go")
	f(ctx, k)
	f(ctx, favContextKey("color"))