Go Resiliency庫中timeout實(shí)現(xiàn)原理及源碼解析
1.go-resiliency簡(jiǎn)介
? 今天看到項(xiàng)目里用到了go-resiliency這個(gè)庫,庫整體比較簡(jiǎn)單,代碼量不大。主要實(shí)現(xiàn)go中幾種常見的模式:
后面分析下這幾種模式的實(shí)現(xiàn)
- circuit-breaker 熔斷器
- semaphore 信號(hào)量
- timeout 函數(shù)超時(shí)
- batching 批處理
- retriable 可重復(fù)
2.timeout模式
先看看模式的test用例
import ( "errors" "testing" "time" ) func takesFiveSecond(stopper <-chan struct{}) error { time.Sleep(5 * time.Second) return nil } func takesTwentySecond(stopper <-chan struct{}) error { time.Sleep(20 * time.Second) return nil } func TestDeadline(t *testing.T) { dl := New(10 * time.Second) //執(zhí)行takesFiveSecond if err := dl.Run(takesFiveSecond); err != nil { t.Error(err) } //執(zhí)行takesTwentySecond if err := dl.Run(takesTwentySecond); err == ErrTimedOut { t.Error(err) } }
- 這里先dl := New(10 * time.Second)創(chuàng)建timeout對(duì)象Deadline,可以看到Deadline只有一個(gè)變量,就是超時(shí)時(shí)間。
- 執(zhí)行函數(shù)調(diào)用dl.Run(takesFiveSecond),如果調(diào)用的函數(shù)執(zhí)行時(shí)間大于變量timeout,會(huì)返回失敗。
3.源碼實(shí)現(xiàn)如下
type Deadline struct { timeout time.Duration } func New(timeout time.Duration) *Deadline { return &Deadline{ timeout: timeout, } }
Deadline對(duì)象只有一個(gè)timeout成員變量
Run核心函數(shù):
//1. 可以看到Run函數(shù)有一個(gè)入?yún)⑹且粋€(gè)函數(shù),函數(shù)的原型為func (<-chan struct{}))error 也就是說我們傳入work變量就需要定義一個(gè)這個(gè)的簽名函數(shù)。 //2. Run函數(shù)返回error,這個(gè)返回實(shí)際是入?yún)ork函數(shù)返回的。 //3.為什么work函數(shù)變量,要有一個(gè)chan了? 這個(gè)主要為了能讓work函數(shù)里來控制,Run提前退出 func (d *Deadline) Run(work func(<-chan struct{}) error) error { result := make(chan error) stopper := make(chan struct{}) //啟動(dòng)一個(gè)協(xié)程 go func() { value := work(stopper) select { case result <- value: case <-stopper: } }() //這里是判斷是否超時(shí)常用手法,通過select監(jiān)聽2個(gè)chan,一個(gè)讀取結(jié)果,一個(gè)為超時(shí)定時(shí)器。 //如果在timeout時(shí)間內(nèi)未讀取到執(zhí)行結(jié)果,就觸發(fā)time.After返回超時(shí) select { case ret := <-result: return ret case <-time.After(d.timeout): close(stopper) return ErrTimedOut } }
Run函數(shù)定義:Run(work func(<-chan struct{}) error) error :
- 可以看到Run函數(shù)有一個(gè)入?yún)⑹且粋€(gè)函數(shù),函數(shù)的原型為func (<-chan struct{}))error 也就是說我們傳入work變量就需要定義一個(gè)這個(gè)的簽名函數(shù)。
- Run函數(shù)返回error,這個(gè)返回實(shí)際是入?yún)ork函數(shù)返回的。
4.擴(kuò)展一下
go語言里超時(shí)控制還有其他常用方式嗎
對(duì)就是context.WithTimeout,讓我們使用context.WithTimeout來重新實(shí)現(xiàn)上面的對(duì)象,只需要修改一個(gè)地方
import ( "context" "errors" "time" ) var ErrTimedOut = errors.New("timed out waiting for function to finish") type ContextTimeOut struct { timeout time.Duration } // New constructs a new Deadline with the given timeout. func New(timeout time.Duration) *ContextTimeOut { return &ContextTimeOut{ timeout: timeout, } } func (d *ContextTimeOut) Run(work func(<-chan struct{}) error) error { result := make(chan error) stopper := make(chan struct{}) go func() { value := work(stopper) select { case result <- value: case <-stopper: } }() ctx, _ := context.WithTimeout(context.Background(), d.timeout) select { case ret := <-result: return ret case <-ctx.Done(): close(stopper) return ErrTimedOut } }
到此這篇關(guān)于Go Resiliency庫中timeout實(shí)現(xiàn)原理及源碼解析的文章就介紹到這了,更多相關(guān)Go Resiliency庫中timeout內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go打印結(jié)構(gòu)體提升代碼調(diào)試效率實(shí)例詳解
這篇文章主要介紹了Go打印結(jié)構(gòu)體提升代碼調(diào)試效率實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-02-02一文詳解Go語言fmt標(biāo)準(zhǔn)庫的常用占位符使用
這篇文章主要為大家詳細(xì)介紹了Go語言中fmt標(biāo)準(zhǔn)庫的常用占位符及其簡(jiǎn)單使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下2022-12-12golang?中?channel?的詳細(xì)使用、使用注意事項(xiàng)及死鎖問題解析
這篇文章主要介紹了golang?中?channel?的詳細(xì)使用、使用注意事項(xiàng)及死鎖分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03基于Go語言構(gòu)建RESTful API服務(wù)
在實(shí)際開發(fā)項(xiàng)目中,你編寫的服務(wù)可以被其他服務(wù)使用,這樣就組成了微服務(wù)的架構(gòu);也可以被前端調(diào)用,這樣就可以前后端分離。那么,本文主要介紹什么是 RESTful API,以及 Go 語言是如何玩轉(zhuǎn) RESTful API 的2021-07-07Go語言常見錯(cuò)誤之濫用getters/setters誤區(qū)實(shí)例探究
在Go語言編程中,恰如其分地使用getters和setters是至關(guān)重要的,過度和不適當(dāng)?shù)厥褂盟鼈兛赡軐?dǎo)致代碼冗余、可讀性差和封裝不當(dāng),在本文中,我們將深入探討如何識(shí)別濫用getter和setter的情況,以及如何采取最佳實(shí)踐來避免這些常見的Go錯(cuò)誤2024-01-01go 代碼的調(diào)試---打印調(diào)用堆棧的實(shí)例
下面小編就為大家?guī)硪黄猤o 代碼的調(diào)試---打印調(diào)用堆棧的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10