zoukankan      html  css  js  c++  java
  • Go context 介绍和使用

    context 上下文管理

    context 翻译过来就是上下文管理,主要作用有两个:

    • 控制 goroutine 的超时
    • 保存上下文数据

    WithTimeout

    通过下面的一个简单的 http 例子进行理解

    demo:

    package main
    
    import (
        "fmt"
        "time"
        "net/http"
        "context"
        "io/ioutil"
    )
    
    
    type Result struct{
        r *http.Response
        err error
    }
    
    func process(){
        ctx,cancel := context.WithTimeout(context.Background(),2*time.Second)
        defer cancel()
        tr := &http.Transport{}
        client := &http.Client{Transport:tr}
        c := make(chan Result,1)
        req,err := http.NewRequest("GET","http://www.google.com",nil)
        if err != nil{
            fmt.Println("http request failed,err:",err)
            return
        }
        // 如果请求成功了会将数据存入到管道中
        go func(){
            resp,err := client.Do(req)
            pack := Result{resp,err}
            c <- pack
        }()
    
        select{
        case <- ctx.Done():
            tr.CancelRequest(req)
            fmt.Println("timeout!")
        case res := <-c:
            defer res.r.Body.Close()
            out,_:= ioutil.ReadAll(res.r.Body)
            fmt.Printf("server response:%s",out)
        }
        return
    
    }
    
    func main() {
        process()
    }

    WithValue

    再写一个 context 保存上下文

    demo:

    package main
    
    import (
        "context"
        "fmt"
    )
    
    func add(ctx context.Context,a,b int) int {
        traceId := ctx.Value("trace_id").(string)
        fmt.Printf("trace_id:%v
    ",traceId)
        return a+b
    }
    
    func calc(ctx context.Context,a, b int) int{
        traceId := ctx.Value("trace_id").(string)
        fmt.Printf("trace_id:%v
    ",traceId)
        //再将ctx传入到add中
        return add(ctx,a,b)
    }
    
    func main() {
        //将ctx传递到calc中
        ctx := context.WithValue(context.Background(),"trace_id","123456")
        ret := calc(ctx,20,30)
        fmt.Printf("%d", ret)
    }

    运行结果:

    trace_id:123456
    trace_id:123456
    50

    WithCancel 

    关于 context 官网上也有一个例子非常有用,用来控制开启的 goroutine 的退出释放

    demo:

    package main
    
    import (
        "context"
        "fmt"
    )
    
    func main() {
        // gen generates integers in a separate goroutine and
        // sends them to the returned channel.
        // The callers of gen need to cancel the context once
        // they are done consuming generated integers not to leak
        // the internal goroutine started by gen.
        gen := func(ctx context.Context) <-chan int {
            dst := make(chan int)
            n := 1
            go func() {
                for {
                    select {
                    case <-ctx.Done():
                        return // returning not to leak the goroutine
                    case dst <- n:
                        n++
                    }
                }
            }()
            return dst
        }
    
        ctx, cancel := context.WithCancel(context.Background())
        defer cancel() // cancel when we are finished consuming integers
    
        for n := range gen(ctx) {
            fmt.Println(n)
            if n == 5 {
                break
            }
        }
    }

    WithDeadline

    关于官网中的 WithDeadline 演示的代码例子

    demo:

    package main
    import (
        "context"
        "fmt"
        "time"
    )
    
    func main() {
        d := time.Now().Add(50 * time.Millisecond)
        ctx, cancel := context.WithDeadline(context.Background(), d)
    
        // Even though ctx will be expired, it is good practice to call its
        // cancelation function in any case. Failure to do so may keep the
        // context and its parent alive longer than necessary.
        defer cancel()
    
        select {
        case <-time.After(1 * time.Second):
            fmt.Println("overslept")
        case <-ctx.Done():
            fmt.Println(ctx.Err())
        }
    
    }

    运行结果:

    context deadline exceeded

    ending ~

    每天都要遇到更好的自己.
  • 相关阅读:
    我谈编程语言竞争
    从基础学起----xuld版高手成长手记[1]
    自己动手开发语言.笔记@2014-1-13
    删除 QQ 最新版右键菜单 通过QQ发送文件到手机
    客观评价C#的优点和缺点
    一个会做你就是高手的问题
    计划开发的语言及一些细节求吐槽
    面向接口设计思想
    计划添加的复杂语法
    面向对象中的设计陷阱
  • 原文地址:https://www.cnblogs.com/kaichenkai/p/11352377.html
Copyright © 2011-2022 走看看