通常情况下,我们会在一个 goroutine 中创建一个上下文对象,然后将这个上下文对象传递给另一个或多个 goroutine 进行并发操作。这些 goroutine 可以在上下文对象的作用域内访问上下文对象中的属性,例如超时时间、取消函数等。这样,我们就可以通过上下文对象来控制 goroutine 的执行和停止。
下面是一个简单的示例,演示如何在多个 goroutine 中使用上下文对象:
package main import ( "context" "fmt" "time" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() ch := make(chan string) go worker(ctx, ch, "worker1") go worker(ctx, ch, "worker2") go worker(ctx, ch, "worker3") for { select { case <-ctx.Done(): fmt.Println("main: context is done.") return case msg := <-ch: fmt.Println("main: received message:", msg) } } } func worker(ctx context.Context, ch chan<- string, name string) { for { select { case <-ctx.Done(): fmt.Printf("%s: context is done.\n", name) return default: ch <- fmt.Sprintf("%s: hello", name) time.Sleep(1 * time.Second) } } }
在上面的示例中,我们首先使用 context.WithTimeout()
函数创建了一个带超时的上下文对象 ctx
,并设置超时时间为 3 秒。然后,我们创建了 3 个 goroutine,每个 goroutine 都执行 worker()
函数,其中传递了上下文对象 ctx
和一个带缓冲的字符串通道 ch
。
在 main()
函数中,我们使用 select
语句监听 ctx
上下文对象的取消信号和 ch
通道的消息。当 ctx
上下文对象被取消或超时时,select
语句会选择取消分支并退出程序;当 ch
通道有消息时,select
语句会选择接收分支并打印消息。
在 worker()
函数中,我们使用 select
语句监听 ctx
上下文对象的取消信号和默认分支。当 ctx
上下文对象被取消或超时时,select
语句会选择取消分支并返回;当默认分支被执行时,worker()
函数会向通道 ch
发送一条消息,然后睡眠 1 秒。
通过使用上下文对象 ctx
,我们可以在多个 goroutine 中传递信息和控制并发操作。在这个示例中,我们通过上下文对象 ctx
实现了在超时时间内控制多个 goroutine 的执行和停止。