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

Go語(yǔ)言實(shí)現(xiàn)請(qǐng)求超時(shí)處理的方法總結(jié)

 更新時(shí)間:2023年05月04日 10:51:42   作者:starrySky  
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中實(shí)現(xiàn)請(qǐng)求的超時(shí)控制的方法,主要是通過(guò)timer和timerCtx來(lái)實(shí)現(xiàn)請(qǐng)求的超時(shí)控制,希望對(duì)大家有所幫助

1. 簡(jiǎn)介

本文將介紹Go語(yǔ)言中實(shí)現(xiàn)請(qǐng)求的超時(shí)控制的方法,主要是通過(guò)timertimerCtx來(lái)實(shí)現(xiàn)請(qǐng)求的超時(shí)控制。

但是在本文中,暫未展示在哪些場(chǎng)景下,timerCtx實(shí)現(xiàn)超時(shí)控制相對(duì)于timer實(shí)現(xiàn)的優(yōu)點(diǎn),或者在哪些場(chǎng)景下,timer相對(duì)于timerCtx在哪些場(chǎng)景下使用更為合適,后續(xù)將會(huì)再進(jìn)行描述。

2. 問(wèn)題引入

當(dāng)使用Go語(yǔ)言進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí),程序可能會(huì)因?yàn)檎?qǐng)求處理時(shí)間過(guò)長(zhǎng)而被卡住,無(wú)法繼續(xù)執(zhí)行后續(xù)代碼。這種情況會(huì)導(dǎo)致程序性能下降,用戶體驗(yàn)變差,甚至?xí)?dǎo)致系統(tǒng)崩潰。特別是在高并發(fā)場(chǎng)景下,這種問(wèn)題更加突出。

舉個(gè)例子,假設(shè)我們需要從一個(gè)遠(yuǎn)程服務(wù)獲取一些數(shù)據(jù),我們可以使用Go標(biāo)準(zhǔn)庫(kù)中的http包進(jìn)行網(wǎng)絡(luò)請(qǐng)求。代碼可能類似于以下示例:

func makeRequest(url string) (string, error) {
    // 創(chuàng)建 http.Client 客戶端實(shí)例
    client := &http.Client{}
    // 創(chuàng)建請(qǐng)求
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return "", err
    }
    // 執(zhí)行請(qǐng)求
    resp, err := client.Do(req)
    if err != nil {
        return "", err
    }
    // 讀取響應(yīng)內(nèi)容
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }
    return string(body), nil
}
func main() {
    url := "https://baidu.com"
    result, err := makeRequest(url)
    if err != nil {
        return
    }
}

這里定義了一個(gè)makeRequest函數(shù),該函數(shù)使用http.Client客戶端發(fā)送HTTP請(qǐng)求并返回響應(yīng)體。

但是,如果請(qǐng)求響應(yīng)時(shí)間過(guò)長(zhǎng),程序就會(huì)一直等待直到請(qǐng)求超時(shí)或者響應(yīng)返回。如果是單個(gè)請(qǐng)求的情況下,這種等待可能不會(huì)對(duì)系統(tǒng)產(chǎn)生太大的影響。但是在高并發(fā)場(chǎng)景下,這種情況可能會(huì)導(dǎo)致系統(tǒng)性能大幅下降。

因此,我們需要一種方法來(lái)對(duì)請(qǐng)求進(jìn)行超時(shí)處理,確保程序能夠及時(shí)響應(yīng)其他請(qǐng)求,而不是一直等待。

3. timer的實(shí)現(xiàn)方案

3.1 timer的基本介紹

Timer可以通過(guò)time.NewTimer()time.AfterFunc()函數(shù)創(chuàng)建。NewTimer()函數(shù)創(chuàng)建一個(gè)Timer對(duì)象,該對(duì)象在指定的時(shí)間間隔后向一個(gè)通道發(fā)送一個(gè)當(dāng)前時(shí)間。AfterFunc()函數(shù)則會(huì)在指定的時(shí)間間隔后執(zhí)行一個(gè)函數(shù)。

通過(guò)timer,可以實(shí)現(xiàn)許多常見(jiàn)的任務(wù),比如定期執(zhí)行某個(gè)操作、超時(shí)控制、任務(wù)調(diào)度等。同時(shí),在Go語(yǔ)言中,timer還可以方便地取消或重置,能夠更加靈活地控制程序的運(yùn)行。

所以,這里我們可以使用timer實(shí)現(xiàn)請(qǐng)求的超時(shí)控制,下面我們來(lái)看使用timer來(lái)實(shí)現(xiàn)超時(shí)控制的具體步驟。

3.2 timer實(shí)現(xiàn)超時(shí)控制

如果需要使用timer實(shí)現(xiàn)請(qǐng)求的超時(shí)控制,可以通過(guò)以下步驟來(lái)實(shí)現(xiàn)請(qǐng)求的超時(shí)處理,具體如下:

  • 創(chuàng)建一個(gè)timer對(duì)象??梢允褂?code>time.NewTimer()函數(shù)創(chuàng)建一個(gè)新的timer對(duì)象
  • 啟動(dòng)一個(gè)goroutine來(lái)執(zhí)行具體的業(yè)務(wù)邏輯
  • select語(yǔ)句中處理超時(shí)事件。在select語(yǔ)句中,使用一個(gè)case來(lái)處理timer的超時(shí)事件
  • 在需要控制超時(shí)的地方使用上述邏輯

下面是一個(gè)示例代碼,演示了如何使用timer實(shí)現(xiàn)超時(shí)控制:

package main
import (
    "fmt"
    "time"
)
func main() {
    // 1. 創(chuàng)建一個(gè)timer對(duì)象,等待5秒鐘
    timeout := time.NewTimer(5 * time.Second)
    ch := make(chan string, 1)
    go func() {
       // 2. 這里我們簡(jiǎn)單模擬一個(gè)需要執(zhí)行10秒的操作
       time.Sleep(10 * time.Second)
       ch <- "hello world"
    }()
    // 3. 在select語(yǔ)句中處理超時(shí)事件 或者請(qǐng)求正常返回
    select {
    case <-timeout.C:
        // 執(zhí)行任務(wù)超時(shí)處理
       fmt.Println("操作超時(shí)")
       return
    case result := <-ch:
        // 執(zhí)行正常業(yè)務(wù)流程
       fmt.Println(result)
    }
    // 停止timer
    if !timeout.Stop() {
       <-timeout.C
    }
    // 操作執(zhí)行完成
    fmt.Println("操作執(zhí)行完成")
}

這里在主協(xié)程處通過(guò)NewTimer創(chuàng)建一個(gè)定時(shí)器,然后啟動(dòng)一個(gè)協(xié)程對(duì)任務(wù)進(jìn)行處理,當(dāng)處理完成后,通過(guò)channel告知其他協(xié)程。

在主協(xié)程中,通過(guò)select語(yǔ)句,對(duì)定時(shí)器timerchannel同時(shí)進(jìn)行監(jiān)聽(tīng),當(dāng)任務(wù)執(zhí)行超時(shí)時(shí),則執(zhí)行超時(shí)邏輯;如果任務(wù)在超時(shí)前完成,則執(zhí)行正常處理流程。

通過(guò)這種方式,實(shí)現(xiàn)了請(qǐng)求的超時(shí)處理。

3.3 對(duì)問(wèn)題的解決

下面展示使用 timer 來(lái)實(shí)現(xiàn)對(duì)請(qǐng)求的超時(shí)處理,從而避免程序長(zhǎng)期處于等待狀態(tài),造成系統(tǒng)性能大幅下降。

func makeRequest(url string) (string, error) {
      // 具體的業(yè)務(wù)邏輯
}
func main() {
    url := "https://baidu.com"
    // 設(shè)置超時(shí)時(shí)間為5秒
    timeout := 5 * time.Second
    // 創(chuàng)建一個(gè)計(jì)時(shí)器,等待超時(shí)
    timer := time.NewTimer(timeout)
    // 創(chuàng)建一個(gè) channel,用于接收請(qǐng)求的結(jié)果
    ch := make(chan string, 1)
    // 啟動(dòng)協(xié)程執(zhí)行請(qǐng)求
    go func() {
        result, err := makeRequest(url)
        if err != nil {
            ch <- fmt.Sprintf("Error: %s", err.Error())
            return
        }
        ch <- result
    }()
    // 等待超時(shí)或者請(qǐng)求結(jié)果返回
    select {
    case result := <-ch:
        fmt.Println(result)
    case <-timer.C:
        fmt.Println("Request timed out")
    }
    // 請(qǐng)求完成后,停止定時(shí)器
    if !timer.Stop() {
        <-timer.C
    }
}

在這個(gè)示例中,我們使用 time 包創(chuàng)建一個(gè)計(jì)時(shí)器,等待超時(shí)。同時(shí),我們還創(chuàng)建了一個(gè) channel,用于接收請(qǐng)求的結(jié)果。然后我們啟動(dòng)一個(gè)協(xié)程執(zhí)行請(qǐng)求,一旦請(qǐng)求返回,就會(huì)將結(jié)果發(fā)送到 channel 中。在主協(xié)程中,我們使用 select 語(yǔ)句等待超時(shí)或者請(qǐng)求結(jié)果返回。如果請(qǐng)求在超時(shí)之前返回,就會(huì)從 channel 中接收到結(jié)果并打印出來(lái)。如果請(qǐng)求超時(shí),就會(huì)打印出相應(yīng)的錯(cuò)誤信息。

從而實(shí)現(xiàn)了避免了處理某些場(chǎng)景請(qǐng)求時(shí),避免系統(tǒng)進(jìn)入長(zhǎng)時(shí)間等待的問(wèn)題的出現(xiàn)。

4.timetCtx的實(shí)現(xiàn)方案

雖然,timerselect實(shí)現(xiàn)超時(shí)控制的邏輯并不復(fù)雜,但是在某些場(chǎng)景下,使用timerCtx來(lái)實(shí)現(xiàn)超時(shí)控制,相對(duì)來(lái)說(shuō)是更為簡(jiǎn)單的,而且現(xiàn)有開(kāi)源框架基本上也是通過(guò)該方式來(lái)實(shí)現(xiàn)的。所以接下來(lái),我們來(lái)對(duì)timerCtx進(jìn)行基本介紹,同時(shí)使用timerCtx來(lái)實(shí)現(xiàn)超時(shí)控制。

4.1 timerCtx的基本介紹

timerCtx是一種在Go語(yǔ)言中使用ContextTimer結(jié)合實(shí)現(xiàn)超時(shí)控制的方式。它是一個(gè)自定義的結(jié)構(gòu)體類型,用于封裝定時(shí)器和取消函數(shù),并提供一種方便的方式來(lái)取消goroutine的執(zhí)行,從而避免出現(xiàn)goroutine泄露等問(wèn)題。

4.2 timerCtx的基本使用方式

當(dāng)使用timetCtx實(shí)現(xiàn)超時(shí)控制,通常需要以下幾個(gè)步驟:

  • 調(diào)用 context.WithTimeout() 方法,創(chuàng)建一個(gè)超時(shí)控制的子上下文。
  • 啟動(dòng)一個(gè)協(xié)程來(lái)執(zhí)行任務(wù)。
  • 在主協(xié)程中,通過(guò)select語(yǔ)句調(diào)用 Done() 方法來(lái)判斷是否超時(shí)。如果 Done() 方法返回的 channel 被關(guān)閉,則意味著已經(jīng)超時(shí),需要及時(shí)停止當(dāng)前任務(wù)并返回。
  • 在函數(shù)返回時(shí),調(diào)用取消函數(shù) cancel(),釋放占用的資源。

下面是一個(gè)示例代碼,演示了如何使用timerCtx實(shí)現(xiàn)超時(shí)控制:

package main
import (
    "context"
    "fmt"
    "time"
)
func main() {
    // 創(chuàng)建一個(gè)timerCtx,設(shè)置超時(shí)時(shí)間為3秒
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    // 調(diào)用cancel函數(shù),釋放占用的資源  
    defer cancel()
    // 開(kāi)啟一個(gè)協(xié)程執(zhí)行任務(wù)
    ch := make(chan string, 1)
    go func() {
        // 模擬任務(wù)執(zhí)行,休眠5秒
        time.Sleep(5 * time.Second)
        ch <- "hello world"
    }()
    // 在主協(xié)程中等待timerCtx超時(shí)或任務(wù)完成
    select {
    case <-ctx.Done():
        fmt.Println("timeout")
    case result := <-ch:
        fmt.Println(result)
    }
}

這里在主協(xié)程處通過(guò)context.WithTimeout創(chuàng)建一個(gè)timerCtx,然后啟動(dòng)一個(gè)協(xié)程對(duì)任務(wù)進(jìn)行處理,當(dāng)處理完成后,通過(guò)channel告知其他協(xié)程。

其次,對(duì)于timerCtx來(lái)說(shuō),調(diào)用Done方法將會(huì)返回一個(gè)channal,當(dāng)超時(shí)后,該channel將會(huì)自動(dòng)被關(guān)閉,此時(shí)通過(guò)select,將能夠從該處于close狀態(tài)的channel中接收到數(shù)據(jù)。

因此,在主協(xié)程中,通過(guò)select語(yǔ)句,對(duì)這兩個(gè)channel同時(shí)進(jìn)行監(jiān)聽(tīng),當(dāng)任務(wù)執(zhí)行超時(shí)時(shí),則執(zhí)行超時(shí)邏輯;如果任務(wù)在超時(shí)前完成,則執(zhí)行正常處理流程。通過(guò)這種方式,實(shí)現(xiàn)了請(qǐng)求的超時(shí)處理。

4.3 對(duì)問(wèn)題的解決

下面使用 context.WithTimeoutselect 來(lái)實(shí)現(xiàn)請(qǐng)求的超時(shí)處理,通過(guò)這種方式,避免程序長(zhǎng)期處于等待狀態(tài),具體代碼實(shí)現(xiàn)如:

// 執(zhí)行具體的業(yè)務(wù)邏輯
func makeRequest(ctx context.Context, url string) (string, error) {}
func main() {
    url := "https://baidu.com"
    // 創(chuàng)建一個(gè)不帶超時(shí)的context
    ctx := context.Background()
    // 1. 創(chuàng)建一個(gè)帶超時(shí)的timerCtx
    timeout := 5 * time.Second
    timerCtx, cancel := context.WithTimeout(ctx, timeout)
    //5. 在函數(shù)返回時(shí),調(diào)用取消函數(shù) cancel(),釋放占用的資源。
    defer cancel()
    // 創(chuàng)建一個(gè) channel,用于接收請(qǐng)求的結(jié)果
    ch := make(chan string, 1)
    // 2. 將子上下文傳遞給需要進(jìn)行超時(shí)控制的函數(shù), 啟動(dòng)協(xié)程執(zhí)行請(qǐng)求
    go func() {
       result, err := makeRequest(ctx,url)
        if err != nil {
            ch <- fmt.Sprintf("Error: %s", err.Error())
            return
        }
        ch <- result
    }()
    // 函數(shù)可以通過(guò)調(diào)用 context.Context 對(duì)象的 Done() 方法來(lái)判斷是否超時(shí)。
    // 如果 Done() 方法返回的 channel 被關(guān)閉,則意味著已經(jīng)超時(shí),需要及時(shí)停止當(dāng)前任務(wù)并返回。
    select {
    case result := <-ch:
        fmt.Println(result)
    case <-timerCtx.Done():
        fmt.Println("Request timed out")
    }
}

在這個(gè)例子中,我們使用 context.WithTimeout 創(chuàng)建一個(gè)帶有超時(shí)的 context 對(duì)象,設(shè)置超時(shí)時(shí)間為 5秒鐘。handleRequest來(lái)執(zhí)行對(duì)應(yīng)的任務(wù),將timeCtx傳遞給handleRequest,如果沒(méi)有在對(duì)應(yīng)時(shí)間內(nèi)正常返回,此時(shí)任務(wù)會(huì)直接返回,不會(huì)無(wú)限期執(zhí)行下去。

在任務(wù)執(zhí)行過(guò)程中,通過(guò)select不斷檢查 ctx.Done() 方法的返回值,如果超時(shí)時(shí)間到了,ctx.Done() 的結(jié)果將變?yōu)橐粋€(gè)非 nil 的值,這時(shí)我們就可以在 select 語(yǔ)句中執(zhí)行超時(shí)處理的邏輯。

最后,在任務(wù)返回后,調(diào)用取消函數(shù) cancel(),釋放占用的資源。

從上面timer實(shí)現(xiàn)超時(shí)控制,或者是使用timerCtx的實(shí)現(xiàn)來(lái)看,其實(shí)二者區(qū)別并不大,但是事實(shí)上,現(xiàn)在任務(wù)的超時(shí)控制,基本上都是使用timerCtx實(shí)現(xiàn)的,并非使用timer來(lái)實(shí)現(xiàn)的,后續(xù)將會(huì)對(duì)其進(jìn)行說(shuō)明。

5. 總結(jié)

在這篇文章中,我們通過(guò)網(wǎng)絡(luò)請(qǐng)求這個(gè)常見(jiàn)的場(chǎng)景,描述其可能導(dǎo)致的問(wèn)題,從而引出了請(qǐng)求的超時(shí)控制。同時(shí),在Go語(yǔ)言中,可以同時(shí)通過(guò)timertimerCtx來(lái)實(shí)現(xiàn)超時(shí)控制,在這篇文章中,主要的內(nèi)容,便是簡(jiǎn)單介紹了如何通過(guò)timertimerCtx來(lái)實(shí)現(xiàn)超時(shí)控制,希望對(duì)你有所幫助。

但是,在這篇文章中,并沒(méi)有介紹timerCtx或者timer的實(shí)現(xiàn)原理。同時(shí),也暫未展示在哪些場(chǎng)景下,timerCtx實(shí)現(xiàn)超時(shí)控制相對(duì)于timer實(shí)現(xiàn)的優(yōu)點(diǎn),或者在哪些場(chǎng)景下,timer相對(duì)于timerCtx在哪些場(chǎng)景下使用更為合適,這些內(nèi)容將會(huì)在后文進(jìn)行描述。

到此這篇關(guān)于Go語(yǔ)言實(shí)現(xiàn)請(qǐng)求超時(shí)處理的方法總結(jié)的文章就介紹到這了,更多相關(guān)Go語(yǔ)言請(qǐng)求超時(shí)處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • GoLang?Time時(shí)間操作函數(shù)講解

    GoLang?Time時(shí)間操作函數(shù)講解

    在日常開(kāi)發(fā)中,我們避免不了時(shí)間的使用,我們可能需要獲取當(dāng)前時(shí)間,然后格式化保存,也可能需要在時(shí)間類型與字符串類型之間相互轉(zhuǎn)換等。本文將會(huì)對(duì)?Go?time?包里面的常用函數(shù)和方法進(jìn)行介紹,需要的可以參考一下
    2023-01-01
  • go中如何獲取本機(jī)ip地址

    go中如何獲取本機(jī)ip地址

    這篇文章主要介紹了go中如何獲取本機(jī)ip地址問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 對(duì)Go語(yǔ)言中的context包源碼分析

    對(duì)Go語(yǔ)言中的context包源碼分析

    這篇文章主要對(duì)Go語(yǔ)言中的context包源碼進(jìn)行分析,context包析是1.15,context包定義了一個(gè)Context類型過(guò)這個(gè)Context接口類型,?就可以跨api邊界/跨進(jìn)程傳遞一些值,下面我們就來(lái)對(duì)context包源碼進(jìn)行分析,需要的小伙伴可以參考一下
    2022-02-02
  • go語(yǔ)言題解LeetCode1122數(shù)組的相對(duì)排序

    go語(yǔ)言題解LeetCode1122數(shù)組的相對(duì)排序

    這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode1122數(shù)組的相對(duì)排序,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 最新評(píng)論

    宜都市| 万源市| 蚌埠市| 岳池县| 庄浪县| 师宗县| 大石桥市| 岳阳市| 诸暨市| 安吉县| 军事| 定结县| 壶关县| 昌宁县| 新沂市| 盘山县| 彩票| 宣恩县| 盱眙县| 龙里县| 眉山市| 凉城县| 湟源县| 舞钢市| 溧阳市| 嘉峪关市| 栖霞市| 南木林县| 阿瓦提县| 宁河县| 金乡县| 安溪县| 察隅县| 杨浦区| 延津县| 江山市| 广元市| 精河县| 武清区| 安庆市| 曲阜市|