聊聊golang的context

栏目: IT技术 · 发布时间: 3年前

内容简介:golang的context的主要用途在于在多个goroutine之间传递数据,管理多个goroutine的生命周期。实际的应用场景有比如,在http服务中,每个请求就对应一个goroutine,而请求之中可能又会调用别的api,而产生更多的goroutine,用context来管理这些goroutine就能比较方便在这些goroutine中传递数据和管理。Background() 返回一个空的context,这是一个根节点。TODO()返回的也是一个空的context,它跟Background的区别在于目

golang的context的主要用途在于在多个goroutine之间传递数据,管理多个goroutine的生命周期。实际的应用场景有比如,在http服务中,每个请求就对应一个goroutine,而请求之中可能又会调用别的api,而产生更多的goroutine,用context来管理这些goroutine就能比较方便在这些goroutine中传递数据和管理。

主要方法

func Background() Context

Background() 返回一个空的context,这是一个根节点。

func TODO() Context

TODO()返回的也是一个空的context,它跟Background的区别在于目的,当你使用一个todo的context时,代码维护者便知道当时的设计意图是待定的。

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

WithCancel()派生一个带有取消方法的子context,这在递归操作context时十分有用。

func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

WithDeadline()和WithTimeout()差不对,只不过两者传的参数不一样,一个传的是截止时间,一个是时间间隔。

func WithValue(parent Context, key interface{}, val interface{}) Context

WithValue()能够在context中带一些参数。

管理goroutine的原理

简单了解下context的方法之后,我们来探究一下为什么说context能管理goroutine。先看个小例子:

func doSomething(ch chan int, id int) {
    fmt.Println(id)
    t := rand.Intn(10)
    time.Sleep(time.Duration(t) * time.Second)
    fmt.Printf("I had slept %d seconds.\n", t)
    ch <- 1
}

func SomeGoRoutine() {
    ch := make(chan int)
    for i := 0; i < 3; i++ {
        go doSomething(ch, i)
    }
    <-ch
    fmt.Println("done")
}

/** output:
2
0
1
I had slept 1 seconds.
done
*/

有这样一个场景,我的http服务提供了一个api,在这个api中产生了n个goroutine,当其中一个goroutine发生了错误,我想要结束掉整个请求,返回一些错误信息给调用方。如果不用context,那么我们很容易想到用channel去实现这样的功能,在主函数中阻塞,在goroutine中将数据传进channel中,当channel接收到数据时,结束掉这个请求。context也是类似的原理,通过channel在goroutine之间的传递而实现goroutine的管理。比较有趣的是WithCancel这个方法,跟我们简单用channel去传递数据不同的是,WithCancel是派生一个子context,当子context要结束的时候,是递归地调用cancel方法,它的child也会调用cancel方法。示例如下:

func ContextCancel() {
    ctx := context.Background()
    go func(ctx context.Context) {
        ctx1, cancel := context.WithCancel(ctx)
        go func(ctx1 context.Context) {
            ctx2, _ := context.WithCancel(ctx1)
            select {
            case <-ctx2.Done():
                fmt.Println("ctx2")
            }
        }(ctx1)
        cancel()
    }(ctx)
    time.Sleep(10 * time.Second)
}
/** ouput:
ctx2
*/

欢迎关注我的公众号:onepunchgo,给我留言。

聊聊golang的context

image


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

小米之道

小米之道

(美)克莱•舍基 / 张琪 / 浙江人民出版社 / 2017-10-1 / 49.90元

共享经济、自媒体预言者,“互联网先知”克莱·舍基,继《认知盈余》《人人时代》后,聚焦风口上的小米。资深科技商业观察家金错刀、润米咨询创始人刘润作序推荐。附多篇雷军内部讲话,详细解读成功完成“筑底”后小米的全新商业模式 纵观中国互联网发展史,可以明显发现,本土互联网企业的崛起,几乎都是先引入国外商业模式,然后通过强化本土化特点来构筑自己的壁垒。在这种背景下,小米是名副其实的新物种,它走的是相反......一起来看看 《小米之道》 这本书的介绍吧!

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具