go context

138 阅读1分钟

Context应用场景

Context取消goroutine任务

context.Withcancel

返回一个 cancel 函数,调用 cancel 函数的时候,会触发 context.Done() 函数

package main

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


func demo(ctx context.Context) {
	for {
		time.Sleep(time.Second * 1)
		select {
			case <- ctx.Done():
				fmt.Println("done")
				return
			default:
				fmt.Println("work")
		}
	}
}

func main() {
	ctx, cancelFunc := context.WithCancel(context.Background())
	go demo(ctx)
	time.Sleep(time.Second * 10)
	cancelFunc()
}

原理:调用 cancelFunc 相当于往一个无缓冲的 channel 中写入一条数据,ctx.Done() 当读到数据时则推出 goroutine


Context进行超时控制

context.WithTimeout

超过指定时间之后,会触发 context.Done 函数

package main

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

func demo(ctx context.Context) {
	for {
		time.Sleep(time.Second * 1)
		select {
			case <- ctx.Done():
				fmt.Println("done")
				return
			default:
				fmt.Println("work")
		}
	}
}

func main() {
	ctx, cancelFunc := context.WithDeadline(context.Background(), time.Now().Add(time.Second*5))
	go demo(ctx)
	time.Sleep(time.Second * 10)
	cancelFunc()
}

WithTimeout 效果与 WithDeadline 相同,只是传入的时间参数不同。

package main

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

func demo(ctx context.Context) {
	for {
		time.Sleep(time.Second * 1)
		select {
			case <- ctx.Done():
				fmt.Println("done")
				return
			default:
				fmt.Println("work")
		}
	}
}

func main() {
	ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second * 5)
	go demo(ctx)
	time.Sleep(time.Second * 10)
	cancelFunc()
}

Context传递通用参数

context.WithValue(ctx, "key", value) 把参数设置到 context

context.Value("key") 获取参数

package main

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

func main() {
	ctx := context.WithValue(context.Background(), "name", "111")
	go g1(ctx)

	time.Sleep(time.Second * 1)
}

func g1(ctx context.Context) {
	fmt.Println(ctx.Value("name"))
	fmt.Println("222")

	go g2(context.WithValue(ctx, "name", "444"))
}

func g2(ctx context.Context) {
	fmt.Println("333")
	fmt.Println(ctx.Value("name"))
}