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

詳解Go語言如何利用上下文進(jìn)行并發(fā)計(jì)算

 更新時(shí)間:2024年02月22日 09:24:09   作者:愛發(fā)白日夢的后端  
在Go編程中,上下文(context)是一個(gè)非常重要的概念,它包含了與請求相關(guān)的信息,本文主要來和大家討論一下如何在并發(fā)計(jì)算中使用上下文,感興趣的可以了解下

在Go編程中,上下文(context)是一個(gè)非常重要的概念,它包含了與請求相關(guān)的信息,如截止日期和取消信息,以及在請求處理管道中傳遞的其他數(shù)據(jù)。在并發(fā)編程中,特別是在處理請求時(shí),正確處理上下文可以確保我們尊重和執(zhí)行請求中設(shè)定的限制,如截止時(shí)間。

讓我們通過一些代碼示例來探討如何在并發(fā)計(jì)算中使用上下文,以及如何在處理請求時(shí)尊重上下文所設(shè)定的截止日期和取消要求。

// download 函數(shù)用于下載給定 URL 的內(nèi)容。
func download(ctx context.Context, url string) (string, error) {...}

download 函數(shù)嘗試獲取給定 URL 的內(nèi)容。然而,需要注意的是,每個(gè) URL 的下載內(nèi)容可能不同,因此下載所需的時(shí)間也可能不同。如果在截止日期之前未能完成 URL 的下載,該函數(shù)將返回一個(gè)錯(cuò)誤(截止日期錯(cuò)誤)。

現(xiàn)在,假設(shè)我們需要下載許多 URL,并且我們只有有限的時(shí)間來完成這些下載。我們可以使用 errgroup 來并發(fā)地進(jìn)行下載,如果超過截止時(shí)間,我們將取消所有并發(fā)操作。

// downloadAll 函數(shù)并發(fā)地下載給定 URL 的內(nèi)容。
func downloadAll(ctx context.Context, urls []string) ([]string, error) {
  results := make([]string, len(urls))

  g, ctx := errgroup.WithContext(ctx)
  for i := range len(urls) {
    g.Go(func() error {
      content, err := download(ctx, urls[i])
      if err != nil {
        return err
      }

      results[i] = content
      return nil
    })
  }

  if err := g.Wait(); err != nil {
    return nil, err
  }

  return results, nil
}

在這個(gè)示例中,downloadAll 函數(shù)同時(shí)下載每個(gè)給定的 URL,并將相同的上下文傳遞給 download 函數(shù)。如果下載任何一個(gè) URL 所需的時(shí)間超過了設(shè)定的截止時(shí)間,download 函數(shù)將失敗,從而導(dǎo)致整個(gè)并發(fā)流程也失敗,downloadAll 將返回一個(gè)截止日期錯(cuò)誤。

除了下載這些 URL,我們還需要處理下載的內(nèi)容。例如,我們可能要對每個(gè) URL 的內(nèi)容應(yīng)用某個(gè)過濾器(謂詞)。

// filter 函數(shù)檢查給定內(nèi)容是否符合給定的謂詞。
func filter(content string, pred func(string) bool) bool {
  return pred(content)
}

請注意,過濾器既不需要上下文,也不進(jìn)行任何跨邊界調(diào)用。過濾器函數(shù)不關(guān)心上游處理的截止日期。

使用 filter 函數(shù),我們可以定義一個(gè)過濾所有內(nèi)容的函數(shù)。

// filterAll 函數(shù)同時(shí)過濾所有給定的內(nèi)容。
func filterAll(contents []string, pred func(string) bool) []string {
  type Result struct {
    content string
    ok      bool
  }

  results := make([]Result, len(contents))

  g := errgroup.Group{}
  for i, content := range contents {
    g.Go(func() error {
      ok := filter(contents[i], pred)
      results[i] = Result{content: content, ok: ok}

      return nil
    })
  }

  g.Wait()

  var filtered []string
  for _, r := range results {
    if r.ok {
      filtered = append(filtered, r.content)
    }
  }

  return filtered
}

filterAll 函數(shù)調(diào)用 filter 函數(shù)來應(yīng)用謂詞到每個(gè)內(nèi)容上,但謂詞的應(yīng)用可能會(huì)花費(fèi)一些時(shí)間,可能超過上下文設(shè)置的截止時(shí)間。由于 filter 函數(shù)不使用上下文,因此它不會(huì)因?yàn)榻刂谷掌阱e(cuò)誤而失敗。

我們需要重新定義 filterAll,使其使用上下文并檢查其中的錯(cuò)誤,而不管 filter 函數(shù)是否使用了上下文。

// filterAll 函數(shù)同時(shí)過濾所有內(nèi)容,并檢查上下文中的錯(cuò)誤。
func filterAll(ctx context.Context, contents []string, pred func(string) bool) ([]string, error) {
  type Result struct {
    content string
    ok      bool
  }

  results := make([]Result, len(contents))

  g, ctx := errgroup.WithContext(ctx)
  for i, content := range contents {
    g.Go(func() error {
      if err := ctx.Err(); err != nil {
        return err
      }

      ok := filter(contents[i], pred)
      results[i] = Result{content: content, ok: ok}

      return nil
    })
  }

  if err := g.Wait(); err != nil {
    return nil, err
  }

  var filtered []string
  for _, r := range results {
    if r.ok {
      filtered = append(filtered, r.content)
    }
  }

  return filtered, nil
}

我們的新實(shí)現(xiàn) filterAll 函數(shù)會(huì)檢查上下文中的任何錯(cuò)誤,即使上下文并未直接傳遞給下游函數(shù)(在本例中為 filter)。如果發(fā)生了與上下文相關(guān)的截止日期(或任何其他錯(cuò)誤),整個(gè)過濾過程就會(huì)失敗。

現(xiàn)在,讓我們完成對所有內(nèi)容的處理。

// processURLs 函數(shù)下載每個(gè) URL 的內(nèi)容并對其進(jìn)行過濾。
//
// 處理必須在上下文截止日期內(nèi)完成。
func processURLs(ctx context.Context, urls []string) ([]string, error) {
  contents, err := downloadAll(ctx, urls)
  if err != nil {
    return nil, err
  }

  filtered, err := filterAll(ctx, contents, somePredicate)

  return filtered, err
}

如果任何一個(gè)下載操作花費(fèi)的時(shí)間過長,那么在嘗試獲取內(nèi)容時(shí)就會(huì)發(fā)生截止日期錯(cuò)誤,因?yàn)樯舷挛谋恢苯佑糜?API 調(diào)用。因此,downloadAll 函數(shù)也會(huì)失敗,進(jìn)而導(dǎo)致 processURLs 失敗。

如果所有的 URL 在截止日期內(nèi)都被正確下載,我們將繼

續(xù)對它們進(jìn)行過濾。在對每個(gè)下載內(nèi)容進(jìn)行過濾時(shí),不使用上下文,但 filterAll 函數(shù)明確地檢查上下文中的錯(cuò)誤,如果發(fā)生了與上下文相關(guān)的截止日期(或任何其他錯(cuò)誤),整個(gè)過濾過程就會(huì)失敗。

有時(shí)候,僅僅使用 errgroup.WithContext 是不足以檢測到上下文中的截止日期或其他問題的,特別是當(dāng)上下文未直接使用時(shí)。因此,我們應(yīng)該定期檢查是否仍在時(shí)間限制內(nèi),否則就會(huì)失敗。

最后,我們可以通過編寫 filterAll 的測試來確保我們正確地處理了類似的情況,以確保我們尊重與上下文相關(guān)的任何錯(cuò)誤。

func TestContextError(t *testing.T) {
  ctx, done := context.WithTimeout(context.Background(), time.Nanosecond)
  defer done()

  // 生成我們想要應(yīng)用過濾器的一些數(shù)據(jù)。
  var contents []string = testingContent()

  _, err := filterAll(ctx, contents, thePredicate)
  if err == nil {
    t.Errorf("filterAll() = %v, want error", err)
  }
}

請注意,在測試中,我們期望 filterAll 會(huì)失敗,因?yàn)槲覀冊O(shè)置的超時(shí)時(shí)間只有一納秒。因此,上下文應(yīng)該因?yàn)槌^截止時(shí)間而發(fā)生錯(cuò)誤。如果在啟動(dòng) Goroutine 進(jìn)行下載內(nèi)容過濾時(shí)不檢查 context.Err(),我們將永遠(yuǎn)不會(huì)處理此類錯(cuò)誤。

到此這篇關(guān)于詳解Go語言如何利用上下文進(jìn)行并發(fā)計(jì)算的文章就介紹到這了,更多相關(guān)Go并發(fā)計(jì)算內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談Go語言的代碼質(zhì)量保證

    淺談Go語言的代碼質(zhì)量保證

    代碼質(zhì)量保證是一個(gè)持續(xù)的過程,需要團(tuán)隊(duì)的共同努力,通過結(jié)合代碼風(fēng)格規(guī)范、靜態(tài)分析、測試、代碼審查、持續(xù)集成等多種手段,可以有效提高Go語言項(xiàng)目的代碼質(zhì)量,感興趣的可以了解一下
    2026-05-05
  • Go語言題解LeetCode599兩個(gè)列表的最小索引總和

    Go語言題解LeetCode599兩個(gè)列表的最小索引總和

    這篇文章主要為大家介紹了Go語言題解LeetCode599兩個(gè)列表的最小索引總和示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Golang內(nèi)存管理之內(nèi)存逃逸分析

    Golang內(nèi)存管理之內(nèi)存逃逸分析

    逃逸分析是指由編譯器決定內(nèi)存分配的位置,不需要程序員指定,這篇文章主要為大家詳細(xì)介紹了Golang中內(nèi)存逃逸分析的幾種方法,需要的可以參考一下
    2023-07-07
  • Golang的select多路復(fù)用及channel使用操作

    Golang的select多路復(fù)用及channel使用操作

    這篇文章主要介紹了Golang的select多路復(fù)用及channel使用操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • golang的os包用法詳解

    golang的os包用法詳解

    Go語言的 os 包中提供了操作系統(tǒng)函數(shù)的接口,是一個(gè)比較重要的包。顧名思義,os 包的作用主要是在服務(wù)器上進(jìn)行系統(tǒng)的基本操作,本文將詳細(xì)介紹了golang的os包用法,需要的朋友可以參考下
    2023-05-05
  • Go實(shí)現(xiàn)將任何網(wǎng)頁轉(zhuǎn)化為PDF

    Go實(shí)現(xiàn)將任何網(wǎng)頁轉(zhuǎn)化為PDF

    在許多應(yīng)用場景中,可能需要將網(wǎng)頁內(nèi)容轉(zhuǎn)化為?PDF?格式,使用Go編程語言,結(jié)合一些現(xiàn)有的庫,可以非常方便地實(shí)現(xiàn)這一功能,下面我們就來看看具體實(shí)現(xiàn)方法吧
    2024-11-11
  • Golang中Retry重試實(shí)踐

    Golang中Retry重試實(shí)踐

    本文主要介紹了Golang中Retry重試實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-02-02
  • Golang 在gin框架中如何使用JWT鑒權(quán)

    Golang 在gin框架中如何使用JWT鑒權(quán)

    JWT,全稱 JSON Web Token,是一種開放標(biāo)準(zhǔn)(RFC 7519),用于安全地在雙方之間傳遞信息,這篇文章主要介紹了golang 在Gin框架中使用JWT鑒權(quán),需要的朋友可以參考下
    2024-07-07
  • 一文詳解Go語言io.LimitedReader類型

    一文詳解Go語言io.LimitedReader類型

    這篇文章主要為大家介紹了Go語言io.LimitedReader類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • GO語言embed機(jī)制的使用

    GO語言embed機(jī)制的使用

    本文詳細(xì)介紹了Go語言中使用embed機(jī)制將靜態(tài)文件(如圖片、文本和目錄)嵌入到程序中,包括文件轉(zhuǎn)[]byte、string類型,以及使用FS結(jié)構(gòu)組合多個(gè)文件和目錄的方法,下面就來詳細(xì)的介紹一下
    2026-03-03

最新評論

西充县| 诸城市| 孟村| 永兴县| 石渠县| 湖南省| 建阳市| 九台市| 彩票| 柳河县| 石河子市| 兴化市| 神池县| 横山县| 渝北区| 河曲县| 汉中市| 奉新县| 扎鲁特旗| 阳泉市| 施甸县| 天台县| 额敏县| 山丹县| 南岸区| 新绛县| 柳江县| 黎城县| 江西省| 子洲县| 丰镇市| 修武县| 中西区| 抚顺市| 分宜县| 兴宁市| 抚远县| 应城市| 承德县| 高淳县| 于都县|