• Go Context


    Context

    介绍

    // Context 代表了协程的上下文,用以在父子协程之间传递控制信号,共享变量等操作
    
    // context.Context 接口
    type Context interface {
    	// 当Context自动取消或者到了取消时间被取消后返回
    	Deadline() (deadline time.Time, ok bool)
    	// 当Context被取消或者到了deadline返回一个被关闭的channel
    	Done() <-chan struct{}
    	// 当Context被取消或者关闭后,返回context取消的原因
    	Err() error
    	// 获取 Context 中保存的键值对数据
    	Value(key any) any
    }
    
    

    使用 WithValue() 传递数据

    func A(ctx context.Context) context.Context {
    	time.Sleep(1 * time.Second)
    	fmt.Println("A: ", ctx.Value("main"))
    	ctx = context.WithValue(ctx, "A", "A-1")
    	go B(ctx)
    	return ctx
    }
    
    func B(ctx context.Context) context.Context {
    	time.Sleep(1 * time.Second)
    	fmt.Println("B: ", ctx.Value("main"))
    	fmt.Println("B: ", ctx.Value("A"))
    	return ctx
    }
    
    func main() {
    	ctx := context.WithValue(context.Background(), "main", "main-1")
    	go A(ctx)
    	time.Sleep(3 * time.Second)
    }
    

    使用 WithCancel() 取消操作

    func main() {
    	ctx, cancel := context.WithCancel(context.Background())
    	go Speak(ctx)
    	time.Sleep(3 * time.Second)
    	cancel()
    	time.Sleep(1 * time.Second)
    }
    
    func Speak(ctx context.Context) {
    	for range time.Tick(time.Second) {
    		select {
    		case <-ctx.Done():
    			fmt.Println("我要闭嘴了")
    			return
    		default:
    			fmt.Println("balabalabalabala")
    		}
    	}
    }
    

    使用 WithDeadline() 设置截止时间

    使用 WithTimeout() 设置超时时间

    withTimeout和withDeadline作用是一样的,就是传递的时间参数不同,会通过传入的时间来自动取消Context,都会返回一个cancelFunc方法,通过调用这个方法可以达到提前进行取消
    使用的过程还是建议在自动取消后也调用cancelFunc去停止定时减少不必要的资源浪费
    
    func A(in chan struct{}) {
    	time.Sleep(1 * time.Second)
    	in <- struct{}{}
    }
    
    func B(in chan struct{}) {
    	time.Sleep(3 * time.Second)
    	in <- struct{}{}
    }
    
    func main() {
    	var ch1 = make(chan struct{})
    	var ch2 = make(chan struct{})
    	var ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
    
    	go func() {
    		go A(ch1)
    		select {
    		case <-ctx.Done():
    			fmt.Println("ctx timeout")
    			break
    		case <-ch1:
    			fmt.Println("A Done")
    		}
    	}()
    
    	go func() {
    		go B(ch2)
    		select {
    		case <-ctx.Done():
    			fmt.Println("ctx timeout")
    			break
    		case <-ch2:
    			fmt.Println("B Done")
    		}
    	}()
    	defer cancel()
    	time.Sleep(5 * time.Second)
    }
    
  • 相关阅读:
    【Flink源码】Flink心跳机制
    PreScan快速入门到精通第三十七讲PreScan中使用深度摄像机
    集成elastic-job分布式调度定时任务
    智能合约通过getAmountsOut方法获取最近币对价格
    传输加解密 RuoYi-Vue-PLus 4.x
    DSP-FIR滤波器设计
    Unity演示Leetcode开香槟过程
    Mac安装rocketmq
    android 动画
    【STM32】PWM输出
  • 原文地址:https://blog.csdn.net/qq_43157273/article/details/139810334