context库

context(上下文)概念

在go服务器中,对于每个请求的request都是在单独的goroutine中进行的,处理一个request也可能设计多个goroutine之间的交互, 使用context可以使开发者方便的在这些goroutine里传递request相关的数据、取消goroutine的signal或截止日期。

根节点

  要创建context树,第一步是要有一个根结点。context.Background函数的返回值是一个空的context,经常作为树的根结点,它一般由接收请求的第一个routine创建,不能被取消、没有值、也没有过期时间 。

子节点

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key interface{}, val interface{}) Context

    这四个函数的第一个参数都是父context,返回一个Context类型的值,这样就层层创建出不同的节点。子节点是从复制父节点得到的,并且根据接收的函数参数保存子节点的一些状态值,然后就可以将它传递给下层的routine了。

  • WithCancel函数,返回一个额外的CancelFunc函数类型变量,该函数类型的定义为 :
type CancelFunc func()
  • WithDeadlineWithTimeoutWithCancel多了一个时间参数,它指示context存活的最长时间。如果超过了过期时间,会自动撤销它的子context。所以context的生命期是由父context的routine和deadline共同决定的。
  • WithValue返回parent的一个副本,该副本保存了传入的key/value,而调用Context接口的Value(key)方法就可以得到val。注意在同一个context中设置key/value,若key相同,值会被覆盖。

实例

package main

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

func inc(a int) int {
    res := a+1
    time.Sleep(1*time.Second)
    return res
}

func Add(ctx context.Context,a,b int) int {
    res := 0
    for i:=0;i<a;i++{
        res = inc(res)
        select {
        case <- ctx.Done():
            return -1
        default:

        }
    }

    for i:=0;i<b;i++{
        res = inc(res)
        select {
        case <- ctx.Done():
            return -1
        default:

        }
    }

    return res
}

func main() {
    // case1:正常执行返回正确结果3
    {
        a:=1
        b:=2
        timeout := 3*time.Second
        ctx, _ := context.WithTimeout(context.Background(),timeout)
        res := Add(ctx,a,b)
        fmt.Printf("Compute  %d+%d,result:%d",a,b,res)
    }

    // case2:执行过程中通过程序终止,返回-1
    {
        a:=1
        b:=2
        ctx,cancel := context.WithCancel(context.Background())
        go func() {
            time.Sleep(1*time.Second)
            cancel()
            fmt.Printf("error:%s", ctx.Err())
        }()
        res := Add(ctx,1,2)
        fmt.Printf("Compute %d+%d,result:%d",a,b,res)
    }
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×