理解 Context

原文:https://go-rod.github.io/i18n/zh-CN/#/understand-context

收录该文档时间: 2024-11-21T08:12:38+08:00

理解 Context

​ 在此之前,先确保你已经学会了 GoroutinesChannels。 Context 主要用于在 Goroutines 之间传递上下文信息,包括:取消信号,超时,截止时间,键值对等等。

​ 例如,我们现在有一个长时间运行的函数 heartbeat,它每秒会打印一次 beat

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

import (
    "fmt"
    "time"
)

func main() {
    heartbeat()
}

func heartbeat() {
    tick := time.Tick(time.Second)

    for {
        <-tick
        fmt.Println("beat")
    }
}

​ 假如我们想在按下回车键的时候中断 heartbeat,我们可以这样修改代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func main() {
    stop := make(chan struct{})
    go func() {
        fmt.Scanln()
        close(stop)
    }()

    heartbeat(stop)
}

func heartbeat(stop chan struct{}) {
    tick := time.Tick(time.Second)

    for {
        select {
        case <-tick:
        case <-stop:
            return
        }
        fmt.Println("beat")
    }
}

​ 由于这种代码很常见,Golang 把它抽象为了一个 helper 包来处理这种情况,并称之为 Context。 现在用 Context 重新实现上面的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func main() {
    ctx, stop := context.WithCancel(context.Background())
    go func() {
        fmt.Scanln()
        stop()
    }()

    heartbeat(ctx)
}

func heartbeat(ctx context.Context) {
    tick := time.Tick(time.Second)

    for {
        select {
        case <-tick:
        case <-ctx.Done():
            return
        }
        fmt.Println("beat")
    }
}
最后修改 November 21, 2024: 更新 (12a252e)