聊聊golang的context

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,给我留言。

原文地址:https://blog.51cto.com/14664952/2480624

时间: 2024-11-14 12:20:03

聊聊golang的context的相关文章

golang 之 context包

概述     context是Go中广泛使用的程序包,由Google官方开发,在1.7版本引入.它用来简化在多个go routine传递上下文数据.(手动/超时)中止routine树等操作,比如,官方http包使用context传递请求的上下文数据,gRpc使用context来终止某个请求产生的routine树.每个Context应该视为只读的,通过WithCancel.WithDeadline.WithTimeout和WithValue函数可以基于现有的一个Context(称为父Context

golang中context包学习

摘要 go语言中goroutine之间的关联关系,缺乏维护,在erlang中有专门的机制来保障新开仟程的生命周期, 在go语言中,只能通过channel + select来实现,但不够直观,感觉很绕. Context 通常被译作 上下文 ,它是一个比较抽象的概念.在公司技术讨论时也经常会提到 上下文 .一般理解为程序单元的一个运行状态.现场.快照,而翻译中 上下 又很好地诠释了其本质,上下上下则是存在上下层的传递, 上 会把内容传递给 下 .在Go语言中,程序单元也就指的是Goroutine.

golang context

1. 内部结构之 - timerCtx . type timerCtx struct { cancelCtx timer *time.Timer // Under cancelCtx.mu. deadline time.Time } - 里面有一个 timer,用来触发超时之后的 回调函数,也就是超时之后,帮你 cancel 一下.理论上,你不用在结构体里存一份这个,这里存了这个指针,主要是用来取消这个定时触发,基本上就是因为一个定时器你如果不需要了,就要马上回收这个资源,否则会很耗资源的.例如

Golang Context 详细介绍

Golang context 本文包含对context实现上的分析和使用方式,分析部分源码讲解比价多,可能会比较枯燥,读者可以直接跳过去阅读使用部分. ps: 作者本着开源分享的精神撰写本篇文章,如果出现任何误差务必留言指正,作者会在第一时间内修正,共同维护一个好的开源生态,谢谢!!! 一.简介 作者所讲的context的包名称是: "golang.org/x/net/context" ,希望读者不要引用错误了. 在godoc中对context的介绍如下: Package contex

Golang 高效实践之并发实践context篇

前言 在上篇Golang高效实践之并发实践channel篇中我给大家介绍了Golang并发模型,详细的介绍了channel的用法,和用select管理channel.比如说我们可以用channel来控制几个goroutine的同步和退出时机,但是我们需要close channel通知其他接受者,当通知和通信的内容混在一起时往往比较复杂,需要把握好channel的读写时机,以及不能往已经关闭的channel中再写入数据.如果有没有一种更好的上下文控制机制呢?答案就是文章今天要介绍的context,

grpc 入门(二)-- context

本节是继上一章节Hello world的进一步深入挖掘; 一.grpc 服务接口类型 在godoc的网站上对grpc的端口类型进行了简单的介绍,总共有下面4种类型[1]: gRPC lets you define four kinds of service method: Unary RPCs where the client sends a single request to the server and gets a single response back, just like a nor

golang - gob与rpc

今天和大家聊聊golang中怎么使用rpc,rpc数据传输会涉及到gob编码,所以先讲讲gob,别担心,就算你完全没有接触过gob与rpc,只要知道rpc的中文是远程过程调用,剩下的我都能给你讲明白(带你入门不包你精通)! 一.数据结构编码之gob gob全称为:Go binary Golang自带的一个数据结构序列化编码/解码工具,也就是说gob可以讲go中的一个数据结构序列化成某种东西,还能反序列化!序列化成啥我们后面来看,不管是变成一个字符串,变成二进制流,变成啥先不管,反正作用就是序列化

ContainerDNS

转自社区 本文介绍的 DNS 命名为 ContainerDNS,作为京东商城软件定义数据中心的关键基础服务之一,具有以下特点: 分布式,高可用 自动发现服务域名 后端探活 易于维护.易于动态扩展llllllll,* 容器化部署 图一 ContainerDNS 架构图 ContainerDNS 包括四大组件 DNS Server.Service to DNS .User API .IP status check.这四个组件通过 etcd 集群结合在一起,彼此独立,完全解耦,每个模块可以单独部署和横

蚂蚁Pincap头条

去年(18年)年底想出来看看机会,最后很幸运地拿到了 PingCAP,今日头条的 offer 以及蚂蚁金服的口头 offer.想着可以总结一下经验,分享一下自己这一段”骑驴找马”过的心路历程.当然,一家之言,难免粗浅,如有不妥,敬请指正. 全文有点长,假如只对一家公司感兴趣的话可以直接跳过去: 准备过程 面试: PingCAP 面试: 蚂蚁 面试: 头条 总结 准备过程 我自己是本科毕业后在老东家干了两年多,老东家算是一家”小公司”(毕竟这年头没有 BAT 或 TMD 的 title 都不好意思