并发上下文控制包Context

Context,是golang用来控制并发流程的库,它能方便的将主控程序的停止信号传递到goroutinue中,从而实现一键中止关联goroutinue的执行,除此之外,它还能将外部变量通过Value的接口传递到goroutinue中。Context是一个接口类型,可以看下面的代码的定义,可以提供一类代表上下文的值,此类型值是并发安全的,也就是说它可以被传播给多个goroutinue。

// A Context carries a deadline, cancelation signal, and request-scoped values
// across API boundaries. Its methods are safe for simultaneous use by multiple
// goroutines.
type Context interface {
    // Done returns a channel that is closed when this Context is canceled
    // or times out.
    Done() <-chan struct{}

    // Err indicates why this context was canceled, after the Done channel
    // is closed.
    Err() error

    // Deadline returns the time when this Context will be canceled, if any.
    Deadline() (deadline time.Time, ok bool)

    // Value returns the value associated with key or nil if none.
    Value(key interface{}) interface{}
}

如何获得contexts?

context包提供从现有上下文值派生新上下文值的函数。这些值形成一棵树:当上下文被取消时,从它派生的所有上下文也被取消。
这棵树的树根或者说根节点是一个在contex包中预定义好的Context值,它是全局唯一的。通过调用context.Background函数,我们就可以获取到它。
根节点仅仅是一个最基本的支点,不能被撤销,也不携带任何数据

// Background returns an empty Context. It is never canceled, has no deadline,
// and has no values. Background is typically used in main, init, and tests,
// and as the top-level Context for incoming requests.
func Background() Context

可以通过context.Background()获得一个初始Context。生成的context传递给WithCancel,WithDeadline,With Timeout,WithValue来生成不同的context。

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, val interface{}) Context

这四个能衍生context的函数,都接受一个初始Context作为第一个参数。

自己写的例子

package main
import (
  "fmt"
  "context"
  "time"
)

func subPeriodPrint(ctx context.Context, msg string) {
  for {
    stop := false
    select {
      case <-ctx.Done():
        fmt.Printf("Over
")
        stop = true
      default:
        fmt.Printf("print msg:%s
", msg)
        time.Sleep(time.Second * 1)
    }
    if stop {
      break
    }
  }
}

func main() {
  // cancel 用来主动发送撤销通知,因为是WithTimeout函数,定时时间到了也会撤销
  ctx, cancel := context.WithTimeout(context.Background(), time.Second * 1)
  for i:=0;i <=1;i++ {
    msg := fmt.Sprintf("current count is %d", i)
    go subPeriodPrint(ctx, msg)
  }
  // 可以设置为5秒和2秒查看打印的不同 
  time.Sleep(time.Second * 5)
  fmt.Println("manual cancel")
  cancel()
}

Ctx.WithValue

WithValue可以将参数塞进context里去,可以实现中间件的功能。比如将将用户session和登陆信息在各个requests之间携带。
设置value

ctx := context.WithValue(parentContext, key, value)

获取value

value:=ctx.Value(key)

Go语言实战笔记(二十)| Go Context
Go Concurrency Patterns: Context
Go Concurrency Patterns: Pipelines and cancellation

---恢复内容结束---

原文地址:https://www.cnblogs.com/linyihai/p/10294777.html