iT邦幫忙

2021 iThome 鐵人賽

0
Modern Web

還喝不 go系列 第 21

[13th][Day21] golang context

context 是個處理流程中關於『超時限制』的控制器

lib context
https://pkg.go.dev/context@go1.17.3

常用的 context 方法

WithCancel: cancellation
WithDeadline and WithTimeout: deadline/timeout and cancellation
WithValue: key-value pairs

來看看幾個例子

    ctx, cancel := context.WithCancel(context.Background())

	time.AfterFunc(4*time.Second, func() {
		cancel()
	})

	go func() {
		<-ctx.Done()
		fmt.Println("Context done!")
	}()

	go func() {
		time.Sleep(1 * time.Second)
		fmt.Println("After 1 second:", ctx.Err())
	}()

	go func() {
		time.Sleep(3 * time.Second)
		fmt.Println("After 3 seconds:", ctx.Err())
	}()

	go func() {
		time.Sleep(5 * time.Second)
		fmt.Println("After 5 seconds:", ctx.Err())
	}()

	time.Sleep(6 * time.Second)

上述例子中,會在第四秒時發出 cancel() 訊號
輸出為

After 1 second: <nil>
After 3 seconds: <nil>
Context done!
After 5 seconds: context canceled

第五秒時 本 context 已 cancel


第二個例子


    ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
	_ = cancel // 本例中不使用 cancel

	go func() {
		<-ctx.Done()
		fmt.Println("Context done!")
	}()

	go func() {
		time.Sleep(1 * time.Second)
		fmt.Println("After 1 second:", ctx.Err())
	}()

	go func() {
		time.Sleep(3 * time.Second)
		fmt.Println("After 3 seconds:", ctx.Err())
	}()

	go func() {
		time.Sleep(5 * time.Second)
		fmt.Println("After 5 seconds:", ctx.Err())
	}()

	time.Sleep(6 * time.Second)

上述例子中,使用 WithTimeout 設定本 context 會在第四秒時超時
輸出為

After 1 second: <nil>
After 3 seconds: <nil>
Context done!
After 5 seconds: context deadline exceeded

第三個例子


    ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)

	time.AfterFunc(2*time.Second, func() {
		cancel()
	})

	go func() {
		<-ctx.Done()
		fmt.Println("Context done!")
	}()

	go func() {
		time.Sleep(1 * time.Second)
		fmt.Println("After 1 second:", ctx.Err())
	}()

	go func() {
		time.Sleep(3 * time.Second)
		fmt.Println("After 3 seconds:", ctx.Err())
	}()

	go func() {
		time.Sleep(5 * time.Second)
		fmt.Println("After 5 seconds:", ctx.Err())
	}()

	time.Sleep(6 * time.Second)

同時使用 WithTimeout & cancel()
context 在 cancel 後就不會 time out 了

輸出為

After 1 second: <nil>
Context done!
After 3 seconds: context canceled
After 5 seconds: context canceled

context 可以確保處理流程的安全性(thread-safe),更準確的是指 goroutine-safe
context 是不可變動的,只能基於現有的 context 創出新的 子 context


上一篇
[13th][Day20] http request header(下)
下一篇
[13th][Day22] http response header(上)
系列文
還喝不 go23

尚未有邦友留言

立即登入留言