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

Golang實現(xiàn)協(xié)程超時控制的方式總結(jié)

 更新時間:2023年05月24日 10:31:49   作者:tracy小貓  
我們知道,go協(xié)程如果不做好處理,很容易造成內(nèi)存泄漏,所以對goroutine做超時控制,才能有效避免這種情況發(fā)生,本文為大家整理了兩個常見的Golang超時控制方法,需要的可以收藏一下

Golang對協(xié)程做超時的控制大概有兩種方式,timer 和context。對于并發(fā)情況,又有不同的方式。

我們知道,go協(xié)程如果不做好處理,很容易造成內(nèi)存泄漏。特別是在高并發(fā)的情況下,如果某一個 goroutine 由于意外退出,則會導(dǎo)致接收方一直阻塞,從而掛起主程序。

對goroutine做超時控制,能夠有效避免這種情況發(fā)生。

Timer+Select

time.After 實現(xiàn)超時控制

  • 利用 time.After 啟動了一個異步的定時器,返回一個 channel,當超過指定的時間后,該 channel 將會接受到信號。
  • 啟動了子協(xié)程,函數(shù)執(zhí)行結(jié)束后,將向 channel ch 發(fā)送結(jié)束信號。
  • 使用 select 阻塞等待 done 或 time.After 的信息,若超時,輸出timeout,若沒有超時,則輸出done。
func TestContext12(t *testing.T) {
    ch := make(chan struct{}, 1)
    go func() {
       fmt.Println("running...")
       time.Sleep(3 * time.Second)
       ch <- struct{}{}
   }()
    select {
       case <-ch:
       fmt.Println("done")
       case <-time.After(2 * time.Second):
       fmt.Println("timeout")
   }
}

output:

=== RUN   TestContext12
running...
timeout
--- PASS: TestContext12 (3.01s)
PASS

這里要注意一個點,就是你創(chuàng)建ch 的時候,必須是帶緩沖的。如果不帶,在并發(fā)的情況下會怎樣呢?

NewTimer

也可以新建一個NewTimer,timer.C返回也是一個channel

func TestContext5(t *testing.T) {
   timer := time.NewTimer(time.Duration(time.Millisecond * 900))
   ch := make(chan struct{}, 1)
   go func() {
      fmt.Println("running...")
      time.Sleep(3 * time.Second)
      ch <- struct{}{}
   }()
   select {
   case <-ch:
      fmt.Println("done")
   case <-timer.C:
      fmt.Println("timeout")
   }
}

output:

=== RUN   TestContext5
running...
timeout
--- PASS: TestContext5 (0.90s)
PASS

留一個坑

為什么不需要關(guān)閉ch 管道?什么時候關(guān)閉ch?

Context+Select

  • 第二種方案是利用 context,context.WithTimeout。
  • 它接受一個Context和一個超時時間作為參數(shù),返回一個子Context和一個取消函數(shù)CancelFunc。
  • 取消函數(shù)CancelFunc將釋放子Context與之有關(guān)的資源,因此在子Context中的相關(guān)操作一旦完成,應(yīng)該立即調(diào)用取消函數(shù)CancelFunc。
func TestContext6(t *testing.T) {
   ch := make(chan string)
   timeout, cancel := context.WithTimeout(context.Background(), 2*time.Second)
   defer cancel()
   go func() {
      time.Sleep(time.Second * 3)
      ch <- "done"
   }()
   select {
   case res := <-ch:
      fmt.Println(res)
   case <-timeout.Done():
      fmt.Println("timout", timeout.Err())
   }
}
  • 利用 context.WithTimeou 返回啟動了一個異步的定時器,返回一個 channel,當超過指定的時間后,該 channel 將會接受到信號。
  • 啟動了子協(xié)程,函數(shù)執(zhí)行結(jié)束后,將向 channel ch 發(fā)送結(jié)束信號。
  • 使用 select 阻塞等待 done 或 time.Done的信息,若超時,輸出timeout,若沒有超時,則輸出done。

output:

=== RUN   TestContext6
timout context deadline exceeded
--- PASS: TestContext6 (2.00s)
PASS

context+并發(fā)協(xié)程

并發(fā)協(xié)程使用WaitGroup阻塞主協(xié)程保證生產(chǎn)協(xié)程和消費協(xié)程正常執(zhí)行完成。

func TestContext3(t *testing.T) {
   withTimeout, cancelFunc := context.WithTimeout(context.Background(), time.Second*1)
   waitGroup := sync.WaitGroup{}
   waitGroup.Add(2)
   go func() { //協(xié)程1
      time.Sleep(time.Second)
      fmt.Println("finished 1")
      waitGroup.Done()
   }()
   go func() { //協(xié)程2
      time.Sleep(time.Second * 2)
      fmt.Println("finished 2")
      waitGroup.Done()
   }()
   go func() {
      select {
      case <-withTimeout.Done():
         fmt.Println("timeout")
         return
      default:
         waitGroup.Wait()
         cancelFunc()
         fmt.Println("finished all")
         return //結(jié)束監(jiān)聽協(xié)程
      }
   }()
   <-withTimeout.Done()
}
  • 開啟協(xié)程1,等待1秒輸出。協(xié)程2,等待2秒輸出。
  • context.WithTimeout等待1秒后返回函數(shù)。
  • 1秒后,協(xié)程一輸出。但是協(xié)程二沒輸出,主線程不等待了。直接返回。

output:

=== RUN   TestContext3
finished 1
--- PASS: TestContext3 (1.01s)
PASS

這里多一個問題,留個坑!

goroutine如何超時控制并發(fā)輸出a,b,c并且按照a,b,c的順序輸出?

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

相關(guān)文章

  • Go中l(wèi)og包異或組合配置妙用詳解

    Go中l(wèi)og包異或組合配置妙用詳解

    在 Go 語言的 log 包中,使用“位運算相或” (|) 來配置日志的 flag,可以讓我們靈活地組合多種日志信息輸出選項,下面我們就來看看這種方法的好處和原理吧
    2024-11-11
  • Golang標準庫CGO詳細介紹與使用方法指南

    Golang標準庫CGO詳細介紹與使用方法指南

    CGO提供了golang和C語言相互調(diào)用的機制,某些第三方庫可能只有C/C++的實現(xiàn),完全用純golang的實現(xiàn)可能工程浩大,這時候CGO就派上用場了,這篇文章主要介紹了Golang標準庫CGO詳細介紹與使用方法指南的相關(guān)資料,需要的朋友可以參考下
    2026-05-05
  • Go變量指針的實現(xiàn)示例

    Go變量指針的實現(xiàn)示例

    Go指針存儲變量地址,用于修改變量、避免拷貝、動態(tài)分配,本文就來詳細的介紹一下Go變量指針的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-09-09
  • golang post請求常用的幾種方式小結(jié)

    golang post請求常用的幾種方式小結(jié)

    這篇文章主要介紹了golang post請求常用的幾種方式小結(jié),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go模板template用法詳解

    Go模板template用法詳解

    這篇文章主要介紹了Go標準庫template模板用法詳解;包括GO模板注釋,作用域,語法,函數(shù)等知識,需要的朋友可以參考下
    2022-04-04
  • go語言中l(wèi)inkname的用法

    go語言中l(wèi)inkname的用法

    這篇文章主要介紹了go語言中l(wèi)inkname的用法,本文給點俺家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • Go語言編寫高可用日志收集腳本

    Go語言編寫高可用日志收集腳本

    在分布式系統(tǒng)和微服務(wù)架構(gòu)中,日志是排查問題、審計行為、監(jiān)控狀態(tài)的重要來源,本文將編寫一個輕量級,高可用的日志收集腳本,有需要的小伙伴可以了解下
    2025-09-09
  • golang切片初始化的使用示例

    golang切片初始化的使用示例

    Go語言中,切片可通過直接初始化、數(shù)組初始化、切片表達式等多種方法進行初始化,這些方式提供了靈活的數(shù)據(jù)管理方式,適合不同的編程需求和場景,感興趣的可以了解一下
    2024-10-10
  • Go語言學習之反射的用法詳解

    Go語言學習之反射的用法詳解

    反射指的是運行時動態(tài)的獲取變量的相關(guān)信息。本文將為大家詳細介紹Go語言中反射的用法,文中的示例代碼講解詳細,感興趣的可以了解一下
    2022-04-04
  • 從零封裝Gin框架及項目初始化教程

    從零封裝Gin框架及項目初始化教程

    這篇文章主要為大家介紹了從零封裝Gin框架及項目的初始化教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01

最新評論

江陵县| 屏山县| 蓝田县| 安义县| 揭阳市| 江北区| 秭归县| 上高县| 高青县| 马龙县| 盖州市| 夏河县| 鄄城县| 鄄城县| 阿克陶县| 额济纳旗| 岑巩县| 尚志市| 邮箱| 沧源| 厦门市| 壶关县| 博乐市| 呼伦贝尔市| 横山县| 五峰| 将乐县| 阿巴嘎旗| 陵川县| 晋州市| 永胜县| 五家渠市| 泰安市| 阳新县| 呼玛县| 灵璧县| 普陀区| 百色市| 余姚市| 攀枝花市| 宜州市|