context包介绍
今天学习了一下context,这个包很管用。主要作用:
1. 关闭多个goroutine;
2.通过继承上下文传递变量值。比如用户id等信息,或者记录时间,根context可以设置一个开始时间,然后再最末端的context中拿出该值,计算耗费时间。
context.Context:
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
//
// Done is provided for use in select statements:
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
// func Stream(ctx context.Context, out chan<- Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
// return err
// }
// select {
// case <-ctx.Done():
// return ctx.Err()
// case out <- v:
// }
// }
// }
//
// See https://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancelation.
Done() <-chan struct{}
// If Done is not yet closed, Err returns nil.
// If Done is closed, Err returns a non-nil error explaining why:
// Canceled if the context was canceled
// or DeadlineExceeded if the context's deadline passed.
// After Err returns a non-nil error, successive calls to Err return the same error.
Err() error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
//
// A key identifies a specific value in a Context. Functions that wish
// to store values in Context typically allocate a key in a global
// variable then use that key as the argument to context.WithValue and
// Context.Value. A key can be any type that supports equality;
// packages should define keys as an unexported type to avoid
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stored using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user
//
// import "context"
//
// // User is the type of value stored in the Contexts.
// type User struct {...}
//
// // key is an unexported type for keys defined in this package.
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
// var userKey key = 0
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
// return context.WithValue(ctx, userKey, u)
// }
//
// // FromContext returns the User value stored in ctx, if any.
// func FromContext(ctx context.Context) (*User, bool) {
// u, ok := ctx.Value(userKey).(*User)
// return u, ok
// }
Value(key interface{}) interface{}
主要的函数:
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
自己写的一个例子:
package main
import (
"context"
"fmt"
"time"
)
func testvalue(ctx context.Context) {
//取出父context设置的值。
if v,ok := ctx.Value("test").(string);ok{
fmt.Println(v,ok)
} else {
fmt.Println(v)
}
}
func watch(c context.Context) {
for {
select {
case <-c.Done():
fmt.Println("the func exit")
fmt.Println("it costs:",costtime(c))
return
default:
fmt.Println("it is running")
testvalue(c)
time.Sleep(2*time.Millisecond)
}
}
}
func costtime(ctx context.Context) int64 {
if v,ok := ctx.Value("start").(time.Time);ok {
return time.Now().Sub(v).Nanoseconds() / 1e6
}
return 0
}
func ExecCancel(cancel context.CancelFunc) {
fmt.Println("start exec cancel cause of timeout")
cancel()
}
func main() {
dctx := context.Background()
//ctx,cancel := context.WithCancel(dctx)
//如果是WithTimeOut,那么不用显示地去执行cancel,超时后会自动停止。
ctx,_ := context.WithTimeout(dctx,80*time.Millisecond)
c := context.WithValue(context.WithValue(ctx,"start",time.Now()),"test","haibo")
//defer ExecCancel(cancel)
//testvalue(c)
go watch(c)
time.Sleep(100*time.Millisecond)
//cancel()
time.Sleep(5*time.Millisecond)
fmt.Println("the main gouroutine ends")
}
--------EOF---------
微信分享/微信扫码阅读
微信分享/微信扫码阅读