go-resiliency源码解析之-timeout
生活随笔
收集整理的這篇文章主要介紹了
go-resiliency源码解析之-timeout
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
go-resiliency源碼解析之-timeout
1.go-resiliency簡(jiǎn)介
? 今天看到項(xiàng)目里用到了go-resiliency這個(gè)庫(kù),庫(kù)整體比較簡(jiǎn)單,代碼量不大。主要實(shí)現(xiàn)go中幾種常見(jiàn)的模式:
后面分析下這幾種模式的實(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í)行takesFiveSecondif err := dl.Run(takesFiveSecond); err != nil {t.Error(err)}//執(zhí)行takesTwentySecondif 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 也就是說(shuō)我們傳入work變量就需要定義一個(gè)這個(gè)的簽名函數(shù)。 //2. Run函數(shù)返回error,這個(gè)返回實(shí)際是入?yún)ork函數(shù)返回的。 //3.為什么work函數(shù)變量,要有一個(gè)chan了? 這個(gè)主要為了能讓work函數(shù)里來(lái)控制,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í)常用手法,通過(guò)select監(jiān)聽(tīng)2個(gè)chan,一個(gè)讀取結(jié)果,一個(gè)為超時(shí)定時(shí)器。//如果在timeout時(shí)間內(nèi)未讀取到執(zhí)行結(jié)果,就觸發(fā)time.After返回超時(shí)select {case ret := <-result:return retcase <-time.After(d.timeout):close(stopper)return ErrTimedOut} }Run函數(shù)定義:Run(work func(<-chan struct{}) error) error :
4.擴(kuò)展一下,go語(yǔ)言里超時(shí)控制還有其他常用方式嗎
對(duì)就是context.WithTimeout,讓我們使用context.WithTimeout來(lái)重新實(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 retcase <-ctx.Done():close(stopper)return ErrTimedOut} }總結(jié)
以上是生活随笔為你收集整理的go-resiliency源码解析之-timeout的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【位运算】起床困难综合症(包含错误思路点
- 下一篇: 超越ReLU!SMU:一种新的激活函数,