我命由我,不由天!


  • 搜索
prometheus docker golang linux kubernetes

context

发表于 2021-04-14 | 分类于 golang | 0 | 阅读次数 344

context.WithCancel

package main

import (
	"context"
	"fmt"
)

func main() {
	gen := func(ctx context.Context) <-chan int {
		dst := make(chan int)
		n := 1
		go func() {
			for {
				select {
				case <-ctx.Done():
					return // returning not to leak the goroutine
				case dst <- n:
					n++
				}
			}
		}()
		return dst
	}

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel() // cancel when we are finished consuming integers

	for n := range gen(ctx) {
		fmt.Println(n)
		if n == 5 {
			break
		}
	}
}

  1. context.Background()创建emptyCtx作为父context
  2. context.WithCancel
    1. 创建cancelCtx
    2. 取消子context函数propagateCancel
    3. 返回context 和 cancel函数
  3. cancel()调用cancel函数退出
    1. cancel()会调用close(c.done)关闭管道,而select监听到信号goroutine就会退出

WithDeadline

func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)

到规定时间结束

原理:

  1. 创建定时器,time.After,执行cancel 方法
package main

import (
	"context"
	"fmt"
	"time"
)

func main(){
	minDuration := time.Now().Add(time.Second)
	ctx,cancel := context.WithDeadline(context.Background(),minDuration)
	defer cancel()
	for {
		select {
		case <- ctx.Done():
			fmt.Println("process end")
		case <-time.After(time.Microsecond):
			fmt.Println("time.After end")
			goto breakHere
		}
	}
	fmt.Println("before breakHere")
	breakHere:
	fmt.Println("after breakHere")
}

WithTimeout

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

内部调用withDeadline通过time.Now.Add()

package main

import (
	"context"
	"fmt"
	"time"
)

const shortDuration = 1 * time.Millisecond

func main() {
	// Pass a context with a timeout to tell a blocking function that it
	// should abandon its work after the timeout elapses.
	ctx, cancel := context.WithTimeout(context.Background(), shortDuration)
	defer cancel()

	select {
	case <-time.After(1 * time.Second):
		fmt.Println("overslept")
	case <-ctx.Done():
		fmt.Println(ctx.Err()) // prints "context deadline exceeded"
	}

}

WithValue

作用:互传数据

原理:设置key value 给context,通过valueCtx 中的key value interface属性记录。key必须为compareable

在使用ValueCtx的时候需要注意一点,这里的key不应该设置成为普通的String或者Int类型,为了防止不同的中间件对这个key的覆盖。最好的情况是每个中间件使用一个自定义的key类型,比如这里的FooKey,而且获取Value的逻辑尽量也抽取出来作为一个函数,放在这个middleware的同包中。这样,就会有效避免不同包设置相同的key的冲突问题了。

package main

import (
	"context"
	"fmt"
)

func main() {
	type favContextKey string
	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")
	ctx := context.WithValue(context.Background(), k, "Go")
	f(ctx, k)
	f(ctx, favContextKey("color"))
}
  • 本文作者: Dante
  • 本文链接: https://gaodongfei.com/archives/context
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# golang
leetcode 两数之和
LRU
  • 文章目录
  • 站点概览
Dante

Dante

119 日志
5 分类
5 标签
RSS
Creative Commons
0%
© 2023 Dante
由 Halo 强力驱动
|
主题 - NexT.Pisces v5.1.4
沪ICP备2020033702号