golang中的標準庫context解讀

2022-09-19 05:06:14 字數 3560 閱讀 8284

golang 中的建立乙個新的 goroutine , 並不會返回像c語言類似的pid,所有我們不能從外部殺死某個goroutine,所有我就得讓它自己結束,之前我們用 channel + select 的方式,來解決這個問題,但是有些場景實現起來比較麻煩,例如由乙個請求衍生出的各個 goroutine 之間需要滿足一定的約束關係,以實現一些諸如有效期,中止routine樹,傳遞請求全域性變數之類的功能。於是google 就為我們提供乙個解決方案,開源了 context 包。使用 context 實現上下文功能約定需要在你的方法的傳入引數的第乙個傳入乙個 context.context 型別的變數。

context.context 介面

context 包的核心

//  context 包裡的方法是執行緒安全的,可以被多個 goroutine 使用    

type context inte***ce

// 在 done 的 channel被closed 後, err 代表被關閉的原因

err() error

// 如果存在,deadline 返回context將要關閉的時間

deadline() (deadline time.time, ok bool)

// 如果存在,value 返回與 key 相關了的值,不存在返回 nil

value(key inte***ce{}) inte***ce{}

}

我們不需要手動實現這個介面,context 包已經給我們提供了兩個,乙個是 background(),乙個是 todo(),這兩個函式都會返回乙個 context 的例項。只是返回的這兩個例項都是空 context。

cancelctx 結構體繼承了 context ,實現了 canceler 方法:

//*cancelctx 和 *timerctx 都實現了canceler介面,實現該介面的型別都可以被直接canceled

type canceler inte***ce

}

type cancelctx struct // closed by the first cancel call.

mu sync.mutex

children map[canceler]bool // set to nil by the first cancel call

err error // 當其被cancel時將會把err設定為非nil

}func (c *cancelctx) done() <-chan struct{}

func (c *cancelctx) err() error

func (c *cancelctx) string() string

//核心是關閉c.done

//同時會設定c.err = err, c.children = nil

//依次遍歷c.children,每個child分別cancel

//如果設定了removefromparent,則將c從其parent的children中刪除

func (c *cancelctx) cancel(removefromparent bool, err error)

c.mu.lock()

if c.err != nil

c.err = err

close(c.done)

for child := range c.children

c.children = nil

c.mu.unlock()

if removefromparent

}

type timerctx struct
type valuectx struct 

}

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 inte***ce{}, val inte***ce{}) context

withcancel 對應的是 cancelctx ,其中,返回乙個 cancelctx ,同時返回乙個 cancelfunc,cancelfunc 是 context 包中定義的乙個函式型別:type cancelfunc func()。呼叫這個 cancelfunc 時,關閉對應的c.done,也就是讓他的後代goroutine退出。

withdeadline 和 withtimeout 對應的是 timerctx ,withdeadline 和 withtimeout 是相似的,withdeadline 是設定具體的 deadline 時間,到達 deadline 的時候,後代 goroutine 退出,而 withtimeout 簡單粗暴,直接 return withdeadline(parent, time.now().add(timeout))。

withvalue 對應 valuectx ,withvalue 是在 context 中設定乙個 map,拿到這個 context 以及它的後代的 goroutine 都可以拿到 map 裡的值。

使用 context 的程式包需要遵循如下的原則來滿足介面的一致性以及便於靜態分析

不要把 context 存在乙個結構體當中,顯式地傳入函式。context 變數需要作為第乙個引數使用,一般命名為ctx

即使方法允許,也不要傳入乙個 nil 的 context ,如果你不確定你要用什麼 context 的時候傳乙個 context.todo

使用 context 的 value 相關方法只應該用於在程式和介面中傳遞的和請求相關的元資料,不要用它來傳遞一些可選的引數

同樣的 context 可以用來傳遞到不同的 goroutine 中,context 在多個goroutine 中是安全的

帶超時時間的自動取消

func main() 

func add(ctx context.context, a, b int) int

} for i := 0; i < b; i++

} return res

}func inc(res int) int

主動取消

func main() ()

ret := add(ctx, a, b)

fmt.printf("%d + %d = %d", a, b, ret)

}func add(ctx context.context, a, b int) int

} for i := 0; i < b; i++

} return res

}func inc(res int) int

golang中的標準庫http

go語言內建的net http包十分的優秀,提供了http客戶端和服務端的實現。基本的http https請求 get head post和postform函式發出http https請求。url.values,id 程式在使用完response後必須關閉回覆的主體。使用net http包編寫乙個簡...

golang中的標準庫strconv

這一組函式是我們平時程式設計中用的最多的。atoi 函式用於將字串型別的整數轉換為int型別,函式簽名如下。func atoi s string i int,err error 如果傳入的字串引數無法轉換為int型別,就會返回錯誤。func main 結論 atoi 如果轉換成功結果就是正常的數值,...

golang中的標準庫log

go語言內建的log包實現了簡單的日誌服務。本文介紹了標準庫log的基本使用。log包定義了logger型別,該型別提供了一些格式化輸出的方法。本包也提供了乙個預定義的 標準 logger,可以通過呼叫函式print系列 print printf println fatal系列 fatal fata...