最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go Resiliency庫(kù)中timeout實(shí)現(xiàn)原理及源碼解析

 更新時(shí)間:2023年05月11日 08:43:27   作者:soft2967  
Go-Resiliency庫(kù)中的timeout是一種基于協(xié)程的超時(shí)機(jī)制,通過(guò)創(chuàng)建協(xié)程來(lái)執(zhí)行任務(wù)并設(shè)置超時(shí)時(shí)間,若任務(wù)執(zhí)行時(shí)間超時(shí)則中止協(xié)程并返回錯(cuò)誤,需要詳細(xì)了解可以參考下文

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í)行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 也就是說(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 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 也就是說(shuō)我們傳入work變量就需要定義一個(gè)這個(gè)的簽名函數(shù)。
  • Run函數(shù)返回error,這個(gè)返回實(shí)際是入?yún)ork函數(shù)返回的。

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 ret
	case <-ctx.Done():
		close(stopper)
		return ErrTimedOut
	}
}

到此這篇關(guān)于Go Resiliency庫(kù)中timeout實(shí)現(xiàn)原理及源碼解析的文章就介紹到這了,更多相關(guān)Go Resiliency庫(kù)中timeout內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 揭秘Go語(yǔ)言中的反射機(jī)制

    揭秘Go語(yǔ)言中的反射機(jī)制

    在Go語(yǔ)言中,反射是通過(guò)reflect包來(lái)實(shí)現(xiàn)的,通過(guò)使用反射,我們可以在運(yùn)行時(shí)獲取對(duì)象的類(lèi)型信息、訪問(wèn)對(duì)象的字段和方法、動(dòng)態(tài)調(diào)用方法等,反射在很多場(chǎng)景下都非常有用,比如編寫(xiě)通用的代碼、實(shí)現(xiàn)對(duì)象的序列化和反序列化、實(shí)現(xiàn)依賴(lài)注入等,需要的朋友可以參考下
    2023-10-10
  • golang如何去除多余空白字符(含制表符)

    golang如何去除多余空白字符(含制表符)

    這篇文章主要介紹了golang去除多余空白字符(含制表符)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • go下載指定版本的依賴(lài)包圖文詳解

    go下載指定版本的依賴(lài)包圖文詳解

    由于依賴(lài)包的每個(gè)版本都有一個(gè)唯一的目錄,所以在多項(xiàng)目場(chǎng)景中需要使用同一個(gè)依賴(lài)包的多版本時(shí)才不會(huì)產(chǎn)生沖突,下面這篇文章主要給大家介紹了關(guān)于go下載指定版本的依賴(lài)包的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • golang int64轉(zhuǎn)int的方法

    golang int64轉(zhuǎn)int的方法

    這篇文章主要介紹了golang int64轉(zhuǎn)int,本文給大家提供兩種方法 ,將 golang int64 轉(zhuǎn)換為golang int,結(jié)合實(shí)例代碼給大家分享轉(zhuǎn)換方法,需要的朋友可以參考下
    2023-01-01
  • Go語(yǔ)言如何在Web服務(wù)中實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)

    Go語(yǔ)言如何在Web服務(wù)中實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)

    在這篇文章中,我們將通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)演示如何在 Go 語(yǔ)言中使用 Gin 框架實(shí)現(xiàn)優(yōu)雅關(guān)機(jī),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • Go語(yǔ)言Http調(diào)用之Post請(qǐng)求詳解

    Go語(yǔ)言Http調(diào)用之Post請(qǐng)求詳解

    前文我們介紹了如何進(jìn)行 HTTP 調(diào)用,并通過(guò) GET 請(qǐng)求的例子,講述了 query 參數(shù)和 header 參數(shù)如何設(shè)置,以及響應(yīng)體的獲取方法。 本文繼上文,接下來(lái)會(huì)通過(guò) POST 請(qǐng)求,對(duì)其他參數(shù)的設(shè)置進(jìn)行介紹,感興趣的可以了解一下
    2022-12-12
  • 使用golang腳本基于kubeadm創(chuàng)建新的token(問(wèn)題分析)

    使用golang腳本基于kubeadm創(chuàng)建新的token(問(wèn)題分析)

    這篇文章主要介紹了使用golang腳本基于kubeadm創(chuàng)建新的token(問(wèn)題分析),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-10-10
  • golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本詳解

    golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本詳解

    這篇文章主要給大家介紹了關(guān)于golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • 詳解golang?defer?閉包?匿名函數(shù)

    詳解golang?defer?閉包?匿名函數(shù)

    這篇文章主要介紹了golang?defer?閉包?匿名函數(shù)的相關(guān)知識(shí),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • golang提示dial?tcp?172?.217.163.49:443:?connectex:?A?connection?attempt?failed解決

    golang提示dial?tcp?172?.217.163.49:443:?connectex:?A?con

    這篇文章主要為大家介紹了golang提示dial?tcp?172?.217.163.49:443:?connectex:?A?connection?attempt?failed解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07

最新評(píng)論

铜陵市| 皋兰县| 英山县| 邵阳县| 洛川县| 阜南县| 华安县| 杭锦旗| 五常市| 沧州市| 镇平县| 博乐市| 吴旗县| 炉霍县| 泰安市| 柳江县| 昆明市| 江津市| 湖口县| 遵化市| 乐至县| 福鼎市| 朝阳区| 江安县| 阜宁县| 合作市| 丹凤县| 奉新县| 安康市| 社旗县| 奎屯市| 寻乌县| 库尔勒市| 长子县| 岳池县| 庆安县| 芦山县| 温州市| 万州区| 银川市| 内江市|