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

golang Goroutine超時(shí)控制的實(shí)現(xiàn)

 更新時(shí)間:2023年09月14日 10:10:26   作者:一個(gè)搬磚的程序猿  
日常開發(fā)中我們大概率會遇到超時(shí)控制的場景,比如一個(gè)批量耗時(shí)任務(wù)、網(wǎng)絡(luò)請求等,本文主要介紹了golang Goroutine超時(shí)控制的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1.個(gè)人理解 

package main
import (
	"context"
	"fmt"
	"runtime"
	"time"
)
func main() {
	// 為了方便查看設(shè)置的計(jì)數(shù)器
	//go func() {
	//	var o int64
	//	for {
	//		o++
	//		fmt.Println(o)
	//		time.Sleep(time.Second)
	//	}
	//}()
	// 開啟協(xié)程
	for i := 0; i < 100; i++ {
		go func(i int) {
			// 利用context 設(shè)置超時(shí)上下文
			ctx, cancel := context.WithTimeout(context.TODO(), 2*time.Second)
			// 主動退出信號
			endDone := make(chan struct{})
			// 再次開啟子協(xié)程異步處理業(yè)務(wù)邏輯
			go func() {
				select {
				// 監(jiān)聽是否超時(shí)
				case <-ctx.Done():
					fmt.Println("Goroutine timeout")
					return
				// 處理業(yè)務(wù)邏輯
				default:
					if i == 1 {
						time.Sleep(10 * time.Second)
					}
					// 此處代碼會繼續(xù)執(zhí)行
					//fmt.Println("代碼邏輯繼續(xù)執(zhí)行")
					// 主動退出
					close(endDone)
                    return
				}
			}()
			// 監(jiān)聽父協(xié)程狀態(tài)
			select {
			// 超時(shí)退出父協(xié)程,這里需要注意此時(shí)如果子協(xié)程已經(jīng)執(zhí)行并超時(shí),子協(xié)程會繼續(xù)執(zhí)行中直到關(guān)閉,這塊需要關(guān)注下。比如:查看數(shù)據(jù)確定數(shù)據(jù)是否已被修改等。
			case <-ctx.Done():
				fmt.Println("超時(shí)退出", i)
				cancel()
				return
			// 主動關(guān)閉
			case <-endDone:
				fmt.Println("主動退出", i)
				cancel()
				return
			}
		}(i)
	}
	//time.Sleep(8 * time.Second)
	time.Sleep(12 * time.Second)
	// 查看當(dāng)前還存在多少運(yùn)行中的goroutine
	fmt.Println("number of goroutines:", runtime.NumGoroutine())
}

2.go-zero實(shí)現(xiàn)方式

package main
import (
	"context"
	"fmt"
	"runtime/debug"
	"strings"
	"time"
)
var (
	// ErrCanceled是取消上下文時(shí)返回的錯誤。
	ErrCanceled = context.Canceled
	// ErrTimeout是當(dāng)上下文的截止日期過去時(shí)返回的錯誤。
	ErrTimeout = context.DeadlineExceeded
)
// DoOption定義了自定義DoWithTimeout調(diào)用的方法。
type DoOption func() context.Context
// DoWithTimeout運(yùn)行帶有超時(shí)控制的fn。
func DoWithTimeout(fn func() error, timeout time.Duration, opts ...DoOption) error {
	parentCtx := context.Background()
	for _, opt := range opts {
		parentCtx = opt()
	}
	ctx, cancel := context.WithTimeout(parentCtx, timeout)
	defer cancel()
	// 創(chuàng)建緩沖區(qū)大小為1的通道以避免goroutine泄漏
	done := make(chan error, 1)
	panicChan := make(chan interface{}, 1)
	go func() {
		defer func() {
			if p := recover(); p != nil {
				// 附加調(diào)用堆棧以避免在不同的goroutine中丟失
				panicChan <- fmt.Sprintf("%+v\n\n%s", p, strings.TrimSpace(string(debug.Stack())))
			}
		}()
		done <- fn()
	}()
	select {
	case p := <-panicChan:
		panic(p)
	case err := <-done:
		return err
	case <-ctx.Done():
		return ctx.Err()
	}
}
// WithContext使用給定的ctx自定義DoWithTimeout調(diào)用。
func WithContext(ctx context.Context) DoOption {
	return func() context.Context {
		return ctx
	}
}
func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		fmt.Println(1111)
		time.Sleep(time.Second * 5)
		fmt.Println(2222)
		cancel()
	}()
	err := DoWithTimeout(func() error {
		fmt.Println("aaaa")
		time.Sleep(10 * time.Second)
		fmt.Println("bbbb")
		return nil
	}, 3*time.Second, WithContext(ctx))
	fmt.Println(err)
	time.Sleep(15 * time.Second)
	//err := DoWithTimeout(func() error {
	//	fmt.Println(111)
	//	time.Sleep(time.Second * 3)
	//	fmt.Println(222)
	//	return nil
	//}, time.Second*2)
	//
	//fmt.Println(err)
	//time.Sleep(6 * time.Second)
	//
	//fmt.Println("number of goroutines:", runtime.NumGoroutine())
}
package fx
import (
	"context"
	"testing"
	"time"
	"github.com/stretchr/testify/assert"
)
func TestWithPanic(t *testing.T) {
	assert.Panics(t, func() {
		_ = DoWithTimeout(func() error {
			panic("hello")
		}, time.Millisecond*50)
	})
}
func TestWithTimeout(t *testing.T) {
	assert.Equal(t, ErrTimeout, DoWithTimeout(func() error {
		time.Sleep(time.Millisecond * 50)
		return nil
	}, time.Millisecond))
}
func TestWithoutTimeout(t *testing.T) {
	assert.Nil(t, DoWithTimeout(func() error {
		return nil
	}, time.Millisecond*50))
}
func TestWithCancel(t *testing.T) {
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		time.Sleep(time.Millisecond * 10)
		cancel()
	}()
	err := DoWithTimeout(func() error {
		time.Sleep(time.Minute)
		return nil
	}, time.Second, WithContext(ctx))
	assert.Equal(t, ErrCanceled, err)
}

參考文獻(xiàn):

 https://github.com/zeromicro/go-zero/blob/master/core/fx/timeout.go

 一文搞懂 Go 超時(shí)控制_51CTO博客_go 超時(shí)處理

到此這篇關(guān)于golang Goroutine超時(shí)控制的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)go Goroutine超時(shí)控制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go Sentinel 動態(tài)數(shù)據(jù)源配置指南(示例詳解)

    Go Sentinel 動態(tài)數(shù)據(jù)源配置指南(示例詳解)

    本文介紹了如何使用Go語言配置Sentinel的動態(tài)數(shù)據(jù)源,并通過本地文件和Nacos兩種方式實(shí)現(xiàn)動態(tài)配置,通過這種方式,可以靈活地管理和更新限流規(guī)則,提升系統(tǒng)的穩(wěn)定性和響應(yīng)速度,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 使用gin框架搭建簡易服務(wù)的實(shí)現(xiàn)方法

    使用gin框架搭建簡易服務(wù)的實(shí)現(xiàn)方法

    go語言web框架挺多的,本文就介紹了一下如何使用gin框架搭建簡易服務(wù)的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Golang讀寫二進(jìn)制文件方法總結(jié)

    Golang讀寫二進(jìn)制文件方法總結(jié)

    使用?Golang?的?encoding/gob?包讀寫二進(jìn)制文件非常方便,而且代碼量也非常少,本文就來通過兩個(gè)示例帶大家了解一下encoding/gob的具體用法吧
    2023-05-05
  • 源碼剖析Golang中map擴(kuò)容底層的實(shí)現(xiàn)

    源碼剖析Golang中map擴(kuò)容底層的實(shí)現(xiàn)

    之前的文章詳細(xì)介紹過Go切片和map的基本使用,以及切片的擴(kuò)容機(jī)制。本文針對map的擴(kuò)容,會從源碼的角度全面的剖析一下map擴(kuò)容的底層實(shí)現(xiàn),需要的可以參考一下
    2023-03-03
  • 詳解go語言單鏈表及其常用方法的實(shí)現(xiàn)

    詳解go語言單鏈表及其常用方法的實(shí)現(xiàn)

    這篇文章主要介紹了詳解go語言單鏈表及其常用方法的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • GO語言實(shí)現(xiàn)二維碼掃碼的示例代碼

    GO語言實(shí)現(xiàn)二維碼掃碼的示例代碼

    你對二維碼掃碼的流程有困惑嗎,這篇文章就結(jié)合筆者自身的開發(fā)經(jīng)驗(yàn)進(jìn)行分享,讓大家熟悉并掌握此功能,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下吧
    2023-06-06
  • Go中的交叉編譯問題

    Go中的交叉編譯問題

    這篇文章主要介紹了Go中的交叉編譯問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • GOLang單元測試用法詳解

    GOLang單元測試用法詳解

    Go語言中自帶有一個(gè)輕量級的測試框架testing和自帶的go test命令來實(shí)現(xiàn)單元測試和性能測試。本文將通過示例詳細(xì)聊聊Go語言單元測試的原理與使用,需要的可以參考一下
    2022-12-12
  • Golang?單元測試和基準(zhǔn)測試實(shí)例詳解

    Golang?單元測試和基準(zhǔn)測試實(shí)例詳解

    這篇文章主要為大家介紹了Golang?單元測試和基準(zhǔn)測試實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go語言實(shí)現(xiàn)圖片快遞信息識別的簡易方法

    Go語言實(shí)現(xiàn)圖片快遞信息識別的簡易方法

    這篇文章主要為大家介紹了Go語言實(shí)現(xiàn)圖片快遞信息識別的簡易方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10

最新評論

安龙县| 获嘉县| 太谷县| 郯城县| 古丈县| 肥西县| 松原市| 临猗县| 周宁县| 苏尼特右旗| 望奎县| 昌吉市| 临夏市| 威信县| 隆回县| 金山区| 阿克陶县| 绥德县| 叶城县| 卢氏县| 桃园市| 双流县| 太湖县| 吐鲁番市| 吴旗县| 新安县| 青铜峡市| 黔江区| 杭锦后旗| 韶关市| 元谋县| 太和县| 北流市| 合阳县| 克山县| 松溪县| 德钦县| 托克逊县| 林西县| 葫芦岛市| 舟山市|