聊聊golang的context

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

内容简介: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


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

查看所有标签

猜你喜欢:

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

Introduction to Computation and Programming Using Python

Introduction to Computation and Programming Using Python

John V. Guttag / The MIT Press / 2013-7 / USD 25.00

This book introduces students with little or no prior programming experience to the art of computational problem solving using Python and various Python libraries, including PyLab. It provides student......一起来看看 《Introduction to Computation and Programming Using Python》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具