context学习

  • context的struct设计
type Context interface {
    Deadline() (deadline time.Time, ok bool)

    Done() <-chan struct{}

    Err() error

    Value(key interface{}) interface{}
}
  • struct中字段分析
    • Deadline()返回设置的截止时间和有无设置截止时间
    • Done()返回一个只读的chan,用来通知是否要释放资源
    • Err()返回取消的原因
    • Value(key interface{})获取绑定在context上的值,是一个键值对。这个值是线程安全的。(在并发情况下,能够正确处理这个共享变量)
  • context的常用方法实例
    • 参考代码
package main

import(
    "fmt"
    "time"
    "golang.org/x/net/context"
)

type faveContextKey string   //定义别名

func main(){
    fmt.Println("context包学习")
    UseContext()
    UseContextWithDeadline()
    UseContextWithTimeout()
    UseContextWithValue()
}


func UseContext(){
    // 使用withCancel生成上下文
    gen := func (ctx context.Context)<- chan int{
        dst := make(chan int)  //无缓冲,无长度
        n := 1
        fmt.Println("这个函数被调用多少次:",n)  //被调用一次
        go func (){
            for{
                select{
                // 多个case同时满足,就会随机执行case
                case <- ctx.Done():
                    // 关闭上下文
                    fmt.Println("ctx.Done",ctx.Err(),n)
                    return
                case dst <- n:   //要么运行完这个作用域,要么就不用运行
                    n++
                    fmt.Printf("n = %v \n",n)
                }
            }
        }()
        //发送器
        return dst
    }
    ctx,cancel := context.WithCancel(context.Background())
    defer cancel()
    data := gen(ctx)
    for n:= range data{  //接收
        fmt.Println(n)
        if n== 16{
            break
        }
    }
}


func UseContextWithDeadline(){
    // withDeadline作用:设置context的存活期
    d := time.Now().Add(50 * time.Millisecond)
    ctx,cancel := context.WithDeadline(context.Background(),d)
    if ctx == nil{
        fmt.Println("ctx is nil")
        return
    }
    defer cancel()
    select{
    case <-time.After(time.Second*1):
        fmt.Println("overslept")
    case <- ctx.Done():
        fmt.Println(ctx.Err())
    }
}


func UseContextWithTimeout(){
    // withTimeout作用:设置context的存活期
    ctx,cancel := context.WithTimeout(context.Background(),50*time.Millisecond)
    if ctx == nil{
        fmt.Println("ctx is nil")
        return
    }
    defer cancel()
    select{
    case <-time.After(time.Second*1):
        fmt.Println("overslept")
    case <- ctx.Done():
        fmt.Println(ctx.Err())
    }
}

func UseContextWithValue(){
    // withValue作用:带值
    f := func(ctx context.Context,k faveContextKey){
        if v := ctx.Value(k);v!=nil{
            fmt.Printf("key:%v,value:%v \n",k,v)
        }else{
            fmt.Println("key not found!",k)
        }
    }
    k := faveContextKey("language")
    ctx:= context.WithValue(context.Background(),k,"go")
    if ctx==nil{
        fmt.Println("ctx is nil")
    }
    f(ctx,k)
    f(ctx,faveContextKey("color"))
}
  • context包的用途

    • 构建树形关系的上下文,实现上一层的Goruntine控制下一层的Goruntine。通过传递context的对象变量方式对下一层的Goruntine进行管控。通知信号为context对象中的Done()进行控制。
    • 参考用例
01-21 05:20