golang goroutine 生命期管理 标准库的 context 包来通知工作协程退出的方式

package main

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

func longtimeCostFunc(ctx context.Context, c chan <- int) {
    for i := 0; i < 10; i++ {
        select{
        case <-ctx.Done():
            fmt.Println("calculate interrupted")
            return
        case <-time.After(time.Second):
            fmt.Println("calcalating.....")
        }
    }

    c <- 1
    fmt.Println("calculate finished")
}

func main() {
    result := make(chan int, 1)
    ctx, cancel := context.WithCancel(context.Background())
    go longtimeCostFunc(ctx, result)

    select {
    case r := <-result:
        fmt.Println("lontimeCostFunc return:", r)
    case <- time.After(3 * time.Second):
        cancel()
        fmt.Println("too long to wait for the result")
    }

    time.Sleep(time.Minute)

    return
}
 
 
 
调用者通过 context.WithCancel() 获取一个可以取消的 context 及与之关联的取消函数 cancel,然后将获取的 context 传递给工作协程(一般作为第一个参数),工作协程通过 context.Done() 监听此 context 是否已经取消,当监听到取消事件后,工作协程就可以不再继续正常的业务流程可以退出了。当调用者调用取消函数 cancel 时,所有通过 context.Done() 监听此 context 是否取消的工作协程都会收到取消的信号。使用这种方式来管理子协程的生命期的时候,要注意子协程在执行正常的业务流程中要能及时响应 context 已取消的信号
 
context 机制除了可以用来管理协程生命期外,还可以用来在有创建关系的一组协程中共享变量。通过这个特性可以实现类似其他语言的但 golang 没有的线程本地存储特性

posted @ 2019-01-18 09:48  small_lei_it  阅读(963)  评论(0编辑  收藏  举报