亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言怎么實現請求超時處理

發布時間:2023-05-04 15:23:36 來源:億速云 閱讀:114 作者:iii 欄目:開發技術

這篇文章主要介紹“Go語言怎么實現請求超時處理”,在日常操作中,相信很多人在Go語言怎么實現請求超時處理問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Go語言怎么實現請求超時處理”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    1. 簡介

    但是在本文中,暫未展示在哪些場景下,timerCtx實現超時控制相對于timer實現的優點,或者在哪些場景下,timer相對于timerCtx在哪些場景下使用更為合適,后續將會再進行描述。

    2. 問題引入

    當使用Go語言進行網絡請求時,程序可能會因為請求處理時間過長而被卡住,無法繼續執行后續代碼。這種情況會導致程序性能下降,用戶體驗變差,甚至會導致系統崩潰。特別是在高并發場景下,這種問題更加突出。

    舉個例子,假設我們需要從一個遠程服務獲取一些數據,我們可以使用Go標準庫中的http包進行網絡請求。代碼可能類似于以下示例:

    func makeRequest(url string) (string, error) {
        // 創建 http.Client 客戶端實例
        client := &http.Client{}
        // 創建請求
        req, err := http.NewRequest("GET", url, nil)
        if err != nil {
            return "", err
        }
        // 執行請求
        resp, err := client.Do(req)
        if err != nil {
            return "", err
        }
        // 讀取響應內容
        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
        }
    }

    這里定義了一個makeRequest函數,該函數使用http.Client客戶端發送HTTP請求并返回響應體。

    但是,如果請求響應時間過長,程序就會一直等待直到請求超時或者響應返回。如果是單個請求的情況下,這種等待可能不會對系統產生太大的影響。但是在高并發場景下,這種情況可能會導致系統性能大幅下降。

    因此,我們需要一種方法來對請求進行超時處理,確保程序能夠及時響應其他請求,而不是一直等待。

    3. timer的實現方案

    3.1 timer的基本介紹

    Timer可以通過time.NewTimer()time.AfterFunc()函數創建。NewTimer()函數創建一個Timer對象,該對象在指定的時間間隔后向一個通道發送一個當前時間。AfterFunc()函數則會在指定的時間間隔后執行一個函數。

    通過timer,可以實現許多常見的任務,比如定期執行某個操作、超時控制、任務調度等。同時,在Go語言中,timer還可以方便地取消或重置,能夠更加靈活地控制程序的運行。

    所以,這里我們可以使用timer實現請求的超時控制,下面我們來看使用timer來實現超時控制的具體步驟。

    3.2 timer實現超時控制

    如果需要使用timer實現請求的超時控制,可以通過以下步驟來實現請求的超時處理,具體如下:

    • 創建一個timer對象。可以使用time.NewTimer()函數創建一個新的timer對象

    • 啟動一個goroutine來執行具體的業務邏輯

    • select語句中處理超時事件。在select語句中,使用一個case來處理timer的超時事件

    • 在需要控制超時的地方使用上述邏輯

    下面是一個示例代碼,演示了如何使用timer實現超時控制:

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

    這里在主協程處通過NewTimer創建一個定時器,然后啟動一個協程對任務進行處理,當處理完成后,通過channel告知其他協程。

    在主協程中,通過select語句,對定時器timerchannel同時進行監聽,當任務執行超時時,則執行超時邏輯;如果任務在超時前完成,則執行正常處理流程。

    通過這種方式,實現了請求的超時處理。

    3.3 對問題的解決

    下面展示使用 timer 來實現對請求的超時處理,從而避免程序長期處于等待狀態,造成系統性能大幅下降。

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

    在這個示例中,我們使用 time 包創建一個計時器,等待超時。同時,我們還創建了一個 channel,用于接收請求的結果。然后我們啟動一個協程執行請求,一旦請求返回,就會將結果發送到 channel 中。在主協程中,我們使用 select 語句等待超時或者請求結果返回。如果請求在超時之前返回,就會從 channel 中接收到結果并打印出來。如果請求超時,就會打印出相應的錯誤信息。

    從而實現了避免了處理某些場景請求時,避免系統進入長時間等待的問題的出現。

    4.timetCtx的實現方案

    雖然,timerselect實現超時控制的邏輯并不復雜,但是在某些場景下,使用timerCtx來實現超時控制,相對來說是更為簡單的,而且現有開源框架基本上也是通過該方式來實現的。所以接下來,我們來對timerCtx進行基本介紹,同時使用timerCtx來實現超時控制。

    4.1 timerCtx的基本介紹

    timerCtx是一種在Go語言中使用ContextTimer結合實現超時控制的方式。它是一個自定義的結構體類型,用于封裝定時器和取消函數,并提供一種方便的方式來取消goroutine的執行,從而避免出現goroutine泄露等問題。

    4.2 timerCtx的基本使用方式

    當使用timetCtx實現超時控制,通常需要以下幾個步驟:

    • 調用 context.WithTimeout() 方法,創建一個超時控制的子上下文。

    • 啟動一個協程來執行任務。

    • 在主協程中,通過select語句調用 Done() 方法來判斷是否超時。如果 Done() 方法返回的 channel 被關閉,則意味著已經超時,需要及時停止當前任務并返回。

    • 在函數返回時,調用取消函數 cancel(),釋放占用的資源。

    下面是一個示例代碼,演示了如何使用timerCtx實現超時控制:

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

    這里在主協程處通過context.WithTimeout創建一個timerCtx,然后啟動一個協程對任務進行處理,當處理完成后,通過channel告知其他協程。

    其次,對于timerCtx來說,調用Done方法將會返回一個channal,當超時后,該channel將會自動被關閉,此時通過select,將能夠從該處于close狀態的channel中接收到數據。

    因此,在主協程中,通過select語句,對這兩個channel同時進行監聽,當任務執行超時時,則執行超時邏輯;如果任務在超時前完成,則執行正常處理流程。通過這種方式,實現了請求的超時處理。

    4.3 對問題的解決

    下面使用 context.WithTimeoutselect 來實現請求的超時處理,通過這種方式,避免程序長期處于等待狀態,具體代碼實現如:

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

    在這個例子中,我們使用 context.WithTimeout 創建一個帶有超時的 context 對象,設置超時時間為 5秒鐘。handleRequest來執行對應的任務,將timeCtx傳遞給handleRequest,如果沒有在對應時間內正常返回,此時任務會直接返回,不會無限期執行下去。

    在任務執行過程中,通過select不斷檢查 ctx.Done() 方法的返回值,如果超時時間到了,ctx.Done() 的結果將變為一個非 nil 的值,這時我們就可以在 select 語句中執行超時處理的邏輯。

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

    從上面timer實現超時控制,或者是使用timerCtx的實現來看,其實二者區別并不大,但是事實上,現在任務的超時控制,基本上都是使用timerCtx實現的,并非使用timer來實現的,后續將會對其進行說明。

    到此,關于“Go語言怎么實現請求超時處理”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    沾化县| 舞钢市| 安龙县| 曲靖市| 旬阳县| 从化市| 东港市| 云龙县| 鞍山市| 常宁市| 红桥区| 辰溪县| 石屏县| 岳普湖县| 漳州市| 永州市| 小金县| 固原市| 洪泽县| 芦溪县| 龙海市| 启东市| 镶黄旗| 镇宁| 贡山| 英德市| 东港市| 思南县| 安达市| 凯里市| 阜新市| 东兴市| 达日县| 江源县| 荔浦县| 耿马| 山阴县| 双峰县| 牟定县| 阿克陶县| 南靖县|