久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

站長資訊網
最全最豐富的資訊網站

詳解Golang的context

下面由golang教程欄目給大家詳解Golang的context,希望對需要的朋友有所幫助!

詳解Golang的context

前言

是的,今天本來還想出去玩的。買了動車票,然后又睡過頭了。。沒辦法,可能是天意,只好總結一下golang的context,希望能與context之間做一個了斷。

公司里頭大家寫各種服務,必須需要將Context作為第一個參數,剛開始以為主要用于全鏈路排查跟蹤。但是隨著接觸多了,原來不止于此。

正文

1.context詳解

1.1 產生背景

在go的1.7之前,context還是非編制的(包golang.org/x/net/context中),golang團隊發現context這個東西還挺好用的,很多地方也都用到了,就把它收編了,1.7版本正式進入標準庫

context常用的使用姿勢:
1.web編程中,一個請求對應多個goroutine之間的數據交互
2.超時控制
3.上下文控制

1.2 context的底層結構

type Context interface {     Deadline() (deadline time.Time, ok bool)     Done() <-chan struct{}     Err() error     Value(key interface{}) interface{} }

這個就是Context的底層數據結構,來分析下:

字段 含義
Deadline 返回一個time.Time,表示當前Context應該結束的時間,ok則表示有結束時間
Done 當Context被取消或者超時時候返回的一個close的channel,告訴給context相關的函數要停止當前工作然后返回了。(這個有點像全局廣播)
Err context被取消的原因
Value context實現共享數據存儲的地方,是協程安全的(還記得之前有說過map是不安全的?所以遇到map的結構,如果不是sync.Map,需要加鎖來進行操作)

同時包中也定義了提供cancel功能需要實現的接口。這個主要是后文會提到的“取消信號、超時信號”需要去實現。

// A canceler is a context type that can be canceled directly. The // implementations are *cancelCtx and *timerCtx. type canceler interface { 	cancel(removeFromParent bool, err error) 	Done() <-chan struct{} }

那么庫里頭提供了4個Context實現,來供大家玩耍

實現 結構體 作用
emptyCtx type emptyCtx int 完全空的Context,實現的函數也都是返回nil,僅僅只是實現了Context的接口
cancelCtx type cancelCtx struct {
Context
mu sync.Mutex
done chan struct{}

children map[canceler]struct{}
err error
}

繼承自Context,同時也實現了canceler接口
timerCtx type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
繼承自cancelCtx,增加了timeout機制
valueCtx type valueCtx struct {
Context
key, val interface{}
}
存儲鍵值對的數據

1.3 context的創建

為了更方便的創建Context,包里頭定義了Background來作為所有Context的根,它是一個emptyCtx的實例。

var (     background = new(emptyCtx)     todo       = new(emptyCtx) //  )  func Background() Context {     return background }

你可以認為所有的Context是樹的結構,Background是樹的根,當任一Context被取消的時候,那么繼承它的Context 都將被回收。

2.context實戰應用

2.1 WithCancel

實現源碼:

func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { 	c := newCancelCtx(parent) 	propagateCancel(parent, &c) 	return &c, func() { c.cancel(true, Canceled) } }

實戰場景:
執行一段代碼,控制執行到某個度的時候,整個程序結束。

吃漢堡比賽,奧特曼每秒吃0-5個,計算吃到10的用時
實戰代碼:

func main() { 	ctx, cancel := context.WithCancel(context.Background()) 	eatNum := chiHanBao(ctx) 	for n := range eatNum { 		if n >= 10 { 			cancel() 			break 		} 	}  	fmt.Println("正在統計結果。。。") 	time.Sleep(1 * time.Second) }  func chiHanBao(ctx context.Context) <-chan int { 	c := make(chan int) 	// 個數 	n := 0 	// 時間 	t := 0 	go func() { 		for { 			//time.Sleep(time.Second) 			select { 			case <-ctx.Done(): 				fmt.Printf("耗時 %d 秒,吃了 %d 個漢堡 n", t, n) 				return 			case c <- n: 				incr := rand.Intn(5) 				n += incr 				if n >= 10 { 					n = 10 				} 				t++ 				fmt.Printf("我吃了 %d 個漢堡n", n) 			} 		} 	}()  	return c }

輸出:

我吃了 1 個漢堡 我吃了 3 個漢堡 我吃了 5 個漢堡 我吃了 9 個漢堡 我吃了 10 個漢堡 正在統計結果。。。 耗時 6 秒,吃了 10 個漢堡

2.2 WithDeadline & WithTimeout

實現源碼:

func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) { 	if cur, ok := parent.Deadline(); ok && cur.Before(d) { 		// The current deadline is already sooner than the new one. 		return WithCancel(parent) 	} 	c := &timerCtx{ 		cancelCtx: newCancelCtx(parent), 		deadline:  d, 	} 	propagateCancel(parent, c) 	dur := time.Until(d) 	if dur <= 0 { 		c.cancel(true, DeadlineExceeded) // deadline has already passed 		return c, func() { c.cancel(true, Canceled) } 	} 	c.mu.Lock() 	defer c.mu.Unlock() 	if c.err == nil { 		c.timer = time.AfterFunc(dur, func() { 			c.cancel(true, DeadlineExceeded) 		}) 	} 	return c, func() { c.cancel(true, Canceled) } }  func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { 	return WithDeadline(parent, time.Now().Add(timeout)) }

實戰場景:
執行一段代碼,控制執行到某個時間的時候,整個程序結束。

吃漢堡比賽,奧特曼每秒吃0-5個,用時10秒,可以吃多少個
實戰代碼:

func main() {     // ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10)) 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 	chiHanBao(ctx) 	defer cancel() }  func chiHanBao(ctx context.Context) { 	n := 0 	for { 		select { 		case <-ctx.Done(): 			fmt.Println("stop n") 			return 		default: 			incr := rand.Intn(5) 			n += incr 			fmt.Printf("我吃了 %d 個漢堡n", n) 		} 		time.Sleep(time.Second) 	} }

輸出:

我吃了 1 個漢堡 我吃了 3 個漢堡 我吃了 5 個漢堡 我吃了 9 個漢堡 我吃了 10 個漢堡 我吃了 13 個漢堡 我吃了 13 個漢堡 我吃了 13 個漢堡 我吃了 14 個漢堡 我吃了 14 個漢堡 stop

2.3 WithValue

實現源碼:

func WithValue(parent Context, key, val interface{}) Context { 	if key == nil { 		panic("nil key") 	} 	if !reflect.TypeOf(key).Comparable() { 		panic("key is not comparable") 	} 	return &valueCtx{parent, key, val} }

實戰場景:
攜帶關鍵信息,為全鏈路提供線索,比如接入elk等系統,需要來一個trace_id,那WithValue就非常適合做這個事。
實戰代碼:

func main() { 	ctx := context.WithValue(context.Background(), "trace_id", "88888888") 	// 攜帶session到后面的程序中去 	ctx = context.WithValue(ctx, "session", 1)  	process(ctx) }  func process(ctx context.Context) { 	session, ok := ctx.Value("session").(int) 	fmt.Println(ok) 	if !ok { 		fmt.Println("something wrong") 		return 	}  	if session != 1 { 		fmt.Println("session 未通過") 		return 	}  	traceID := ctx.Value("trace_id").(string) 	fmt.Println("traceID:", traceID, "-session:", session) }

輸出:

traceID: 88888888 -session: 1

3.context建議

不多就一個。

Context要是全鏈路函數的第一個參數

func myTest(ctx context.Context)  {     ... }

(寫好了竟然忘記發送了。。。汗)

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
国产精品久久乐| 亚州精品视频| 亚洲精品裸体| 免费黄色成人| 中文字幕视频精品一区二区三区| 麻豆一区二区99久久久久| 亚洲精品2区| 四虎4545www国产精品| 国产中文字幕一区二区三区| 日韩中文av| 久久久91麻豆精品国产一区| 国产精品任我爽爆在线播放| 国产一区二区三区黄网站| 九九精品调教| 日韩影院免费视频| 日本不卡一二三区黄网| 国产乱子精品一区二区在线观看| 欧美日韩黄网站| 国内精品亚洲| 国产精品香蕉| 欧美激情福利| 欧美日韩中文字幕一区二区三区 | 久久精品99久久无色码中文字幕| 亚洲欧美日韩高清在线| 亚洲日本免费电影| 伊人久久在线| 久久高清一区| 日韩av在线中文字幕| 爽好多水快深点欧美视频| 91精品精品| 午夜视频精品| 精品一区二区三区的国产在线观看 | 久久男女视频| 国产成人久久精品麻豆二区| 亚洲啊v在线| 免费观看不卡av| 久久福利影视| 国产精品毛片久久久| 国产精品一级| 精品国产a一区二区三区v免费| 福利视频一区| 国产一区国产二区国产三区 | 99久精品视频在线观看视频| 99国产精品免费视频观看| 99在线精品视频在线观看| 亚洲精选久久| 色爱综合网欧美| 日韩视频在线一区二区三区 | 日韩毛片一区| 日韩电影免费在线观看| 亚洲欧美日韩国产综合精品二区 | 亚洲香蕉久久| 国产精品美女在线观看直播| 欧美日韩国产高清电影| 日本久久二区| 999国产精品视频| 国产欧美成人| 蜜臀国产一区二区三区在线播放 | 日韩精品一区二区三区免费观影 | 激情欧美一区二区三区| 日韩福利视频一区| 91青青国产在线观看精品| 日韩中文字幕亚洲一区二区va在线 | 亚洲69av| 日韩精品免费一区二区三区| 亚洲精品韩国| 夜夜嗨一区二区三区| 久久精品国产99国产| 一区二区国产在线观看| 日韩中文在线电影| 91亚洲精品视频在线观看| 国户精品久久久久久久久久久不卡 | 欧美成人a交片免费看| 欧美日本不卡高清| 激情婷婷综合| 色88888久久久久久影院| 麻豆精品视频在线观看视频| 日韩欧美激情电影| 午夜在线视频一区二区区别| 妖精视频成人观看www| 日本在线成人| 亚洲精品小说| 欧美综合另类| 欧美1级日本1级| 久久久精品日韩| 日本不良网站在线观看| 国产不卡av一区二区| 国产日韩一区| 国产精品视频一区二区三区综合| 一本综合精品| 日韩一区免费| 亚洲一区有码| 青草国产精品久久久久久| 日韩av不卡在线观看| 亚洲欧美不卡| 色老板在线视频一区二区| 久久激情婷婷| 中文日韩在线| 日韩极品在线观看| 国产精品chinese| 国产精品丝袜在线播放| 九九精品调教| 欧美日韩四区| 日本vs亚洲vs韩国一区三区二区| 日韩一区欧美二区| 视频一区中文字幕精品 | 欧美日韩免费观看一区=区三区| 中文字幕系列一区| 免费看黄色91| 日韩福利视频一区| 国产一区二区三区91| 99成人超碰| 亚洲美女久久| 久久天堂影院| 免费精品国产的网站免费观看| 日韩av一区二区在线影视| 国产一区二区三区日韩精品| 欧美午夜不卡| 精品国产美女a久久9999| 欧美欧美黄在线二区| 日韩欧美网址| 日韩av一区二区在线影视| 麻豆国产精品777777在线| 激情欧美一区二区三区| 国产伦乱精品| 成人精品中文字幕| 国产精品久久久久久av公交车| 欧美69视频| 久久久久久色| 肉色欧美久久久久久久免费看| 视频在线观看一区| 亚洲精品永久免费视频| 日精品一区二区三区| 麻豆91小视频| 国产日韩欧美三区| 久久狠狠久久| 欧美亚洲三区| 日韩国产在线观看| 亚洲精品韩国| 亚洲va久久| 乱一区二区av| 久久婷婷丁香| 亚洲免费影视| 日韩高清一区在线| 麻豆精品在线播放| 久久久久久久久久久9不雅视频| 亚洲欧美一区在线| 蜜桃久久久久久| 久久99久久久精品欧美| 福利一区和二区| 99免费精品| 免费在线看一区| 一区二区日韩免费看| 91伊人久久| 日韩欧美一区二区三区在线视频| 欧美精选一区二区三区| 日韩黄色免费网站| 久久久久网站| 7777精品| 欧美亚洲精品在线| 亚洲精品一级| 亚洲精品一区三区三区在线观看| 午夜亚洲一区| 另类专区亚洲| 中文字幕视频精品一区二区三区| 免费看久久久| 亚洲制服一区| 国产精品qvod| 综合欧美亚洲| 久久久久久黄| 亚洲精品看片| 91国语精品自产拍| 免费在线成人网| 国产夫妻在线| 牛牛精品成人免费视频| 蜜臀av国产精品久久久久| 日本久久黄色| 欧美日韩中出| 蜜臀精品一区二区三区在线观看| 中文字幕高清在线播放| 日本视频一区二区| 久久人人88| 国产成人精选| 日韩精品国产欧美| 亚洲欧美成人综合| 久久久精品日韩| 在线天堂中文资源最新版| 国产欧美一区二区精品久久久| 亚洲区第一页| 亚洲精品福利| 亚洲精品欧洲| 精品国产欧美| 在线一区视频观看| 一区免费视频| 日本激情一区| 免费在线看一区| 欧美91在线| 私拍精品福利视频在线一区| 日韩一级不卡| 国产精东传媒成人av电影|