搜尋
首頁後端開發Golanggolang並發請求接口

Go語言是一種非常適合併發程式設計的程式語言,在實現高並發的服務或應用時,它的效能得到了很好的發揮。在日常開發中,我們可能會遇到需要並發請求介面或並發處理大量的資料的場景,本文將介紹golang中如何實作並發請求介面。

並發請求介面的場景

在實際開發中,我們可能會遇到需要請求某個介面並取得回應資料的場景,例如:

  • 取得某個網站上的商品資料。
  • 從不同的API介面取得資料並彙總呈現。
  • 同時請求多個資料來源以便快速收集資料。

在單線程中,如果需要請求多個接口,那麼需要一個接口請求完成之後再去請求另一個接口,這會導致整個流程變得緩慢。相反,使用並發請求介面則可以同時啟動多個請求,大幅提高請求效率。

goroutine並發處理

goroutine是go語言中的一種特殊的函數,它可以在與主執行緒並行的特殊執行緒中運行。多個goroutine同時運行可以同時請求多個接口,請求完成之後再進行資料整合處理。並發使用goroutine比較容易實現,透過go關鍵字實現即可。

WaitGroup控制goroutine

在實際開發中,我們可能會發現可能有一些協程可能比較耗時,可能需要更多的時間才能回傳結果。在這種情況下,我們需要等待協程返回結果,進行後面的處理。這時候,我們需要使用sync.WaitGroup來控制goroutine數量,確保所有請求都得到回應結果。

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "sync"
)

var wg sync.WaitGroup // 声明一个sync.WaitGroup实例,用于协程控制

func main() {
    urls := []string{"https://www.baidu.com", "https://www.qq.com", "https://www.taobao.com", "https://www.jd.com", "https://www.mi.com"}

    // 通过遍历urls,启动goroutine
    for _, url := range urls {
        wg.Add(1) // 添加一个goroutine
        go getBody(url)
    }

    wg.Wait() // 等待所有goroutine结束
}

// getBody用于获取传入url的响应结果,并打印。
func getBody(url string) {
    resp, err := http.Get(url) // 发起http GET请求
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("url: %s, contents:
%s
", url, string(body))
    wg.Done() // 相当于wg.Add(-1),标志该goroutine已经结束
}

在上面的程式碼中,我們先宣告了一個sync.WaitGroup實例,用於協程數量控制。然後,在main()函數中,透過遍歷urls啟動了多個協程,同時每次啟動協程時,都會呼叫wg.Add(1)方法,表示需要等待一個協程完成。這樣的話,WaitGroup中記錄的等待的協程數量就會變成urls中url數量。然後在go getBody(url)這一行,我們啟動了請求url的協程,然後在協程結束的時候呼叫了wg.Done()方法,表示該協程已經結束。

最後,wg.Wait()呼叫使主協程等待所有協程結束。

並發請求的最佳實踐

在實際開發中,我們需要注意一些細節,這些細節可以幫助我們更好地使用並發請求介面。

一、並發數量的控制

在並發請求介面的時候,我們需要控制並發的數量,特別是當介面請求數量比較大時,避免一次性請求使伺服器受到太大壓力。我們可以設立一個最大值,這樣可以保證並發的最高數量。我們可以使用golang中的緩衝通道來實現最大並發數的控制。

ch := make(chan struct{}, 5) // 声明一个缓冲通道,大小为5,控制并发数量为5

for _, url := range urls {
    ch <- struct{}{} // 把协程数量放在通道里
    wg.Add(1)  // 添加一个goroutine
    go func(url string) {
        defer wg.Done()
        getBody(url)
        <-ch // 从通道里取出一个值,表示这个协程已经结束
    }(url)
}

在宣告緩衝通道的過程中,我們設定緩衝大小為5,表示最多同時運行5個goroutine,接著我們遍歷urls,向通道中加入結構體值。

在啟動goroutine的時候,我們宣告了一個func(url string)為處理函數,避免同時運行goroutine的最大數量超過5個,然後呼叫getBody(url )方法。在goroutine結束的時候,我們透過通道釋放一個訊號,表示有一個goroutine結束了—

二、避免請求阻塞

在進行並發請求介面的時候,我們需要避免請求阻塞,通常出現在一個請求長時間沒有對應時。我們可以使用Golang中的context.Context來解決這個問題。如果請求逾時,則取消阻塞的請求。

url := "https://httpstat.us/200?sleep=8000"

ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*5000) // 告诉请求,5秒之后自动取消

defer cancel()

req, err := http.NewRequestWithContext(ctx, "GET", url, nil) // 使用请求上下文

if err != nil {
    log.Fatal(err)
}

client := http.DefaultClient
resp, err := client.Do(req) // 发起请求
if err != nil {
    log.Fatal(err)
}

if resp.StatusCode == http.StatusOK {
    contents, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s
", contents)
}

在上面的程式碼中,我們使用了context.WithTimeout方法建立了一個請求上下文,其timeout設定為5秒,例如http://httpstat.us/200? sleep=8000,這個請求需要8秒才能回傳資料。然後我們使用http.NewRequestWithContext方法來建立一個使用請求上下文的請求。在發送請求時,我們使用http.DefaultClient發起請求。最後,如果響應狀態碼是200,則輸出響應資料。

當請求逾時時,請求連結就會被直接關掉。這時我們會受到「context deadline exceeded」錯誤的提示。

三、避免請求重複

在請求接口時,可能會遇到重複請求同一個接口的情況,在這種情況下,我們應該避免重複請求同一個接口,這會浪費寶貴的時間和資源。我們可以使用Golang中的sync.Map來解決這個問題。

var m = sync.Map{}

url := "https://httpbin.org/get"

wg.Add(2)
go doGet(url, &m, &wg)
go doGet(url, &m, &wg)

wg.Wait()

func doGet(url string, m *sync.Map, wg *sync.WaitGroup) {
    _, loaded := m.LoadOrStore(url, true) // 表示url已经被请求过,如果已存在,则直接返回,否则返回false并储存

    if loaded {
        fmt.Printf("url %s already requested.
", url)
        wg.Done()
        return
    }

    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }

    defer resp.Body.Close()
    contents, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s
", contents)
    wg.Done()
}

在上面的程式碼中,我們使用了一個sync.Map來保證url只被要求一次。在doGet協程中,我們使用m.LoadOrStore(url, true)來判斷url是否已經被請求過,如果請求過了,就return直接退出協程。否則,我們發起http.Get請求並在log中列印回應資料。最後,我們透過wg.Done()方法標誌協程已經結束。

總結

本文介紹了使用golang實作並發請求介面的方法。透過使用goroutine並發處理,WaitGroup協程控制,以及緩衝通道控制並發數量。透過在請求上下文中設定逾時來避免請求阻塞,並且使用sync.Map避免請求重複。透過使用這些技術,我們可以大幅提高請求介面的效率,提升編碼效率和程式設計體驗。

以上是golang並發請求接口的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Golang和Python:了解差異Golang和Python:了解差異Apr 18, 2025 am 12:21 AM

Golang和Python的主要區別在於並發模型、類型系統、性能和執行速度。 1.Golang使用CSP模型,適用於高並發任務;Python依賴多線程和GIL,適合I/O密集型任務。 2.Golang是靜態類型,Python是動態類型。 3.Golang編譯型語言執行速度快,Python解釋型語言開發速度快。

Golang vs.C:評估速度差Golang vs.C:評估速度差Apr 18, 2025 am 12:20 AM

Golang通常比C 慢,但Golang在並發編程和開發效率上更具優勢:1)Golang的垃圾回收和並發模型使其在高並發場景下表現出色;2)C 通過手動內存管理和硬件優化獲得更高性能,但開發複雜度較高。

Golang:雲計算和DevOps的關鍵語言Golang:雲計算和DevOps的關鍵語言Apr 18, 2025 am 12:18 AM

Golang在雲計算和DevOps中的應用廣泛,其優勢在於簡單性、高效性和並發編程能力。 1)在雲計算中,Golang通過goroutine和channel機制高效處理並發請求。 2)在DevOps中,Golang的快速編譯和跨平台特性使其成為自動化工具的首選。

Golang和C:了解執行效率Golang和C:了解執行效率Apr 18, 2025 am 12:16 AM

Golang和C 在執行效率上的表現各有優勢。 1)Golang通過goroutine和垃圾回收提高效率,但可能引入暫停時間。 2)C 通過手動內存管理和優化實現高性能,但開發者需處理內存洩漏等問題。選擇時需考慮項目需求和團隊技術棧。

Golang vs. Python:並發和多線程Golang vs. Python:並發和多線程Apr 17, 2025 am 12:20 AM

Golang更適合高並發任務,而Python在靈活性上更有優勢。 1.Golang通過goroutine和channel高效處理並發。 2.Python依賴threading和asyncio,受GIL影響,但提供多種並發方式。選擇應基於具體需求。

Golang和C:性能的權衡Golang和C:性能的權衡Apr 17, 2025 am 12:18 AM

Golang和C 在性能上的差異主要體現在內存管理、編譯優化和運行時效率等方面。 1)Golang的垃圾回收機制方便但可能影響性能,2)C 的手動內存管理和編譯器優化在遞歸計算中表現更為高效。

Golang vs. Python:申請和用例Golang vs. Python:申請和用例Apr 17, 2025 am 12:17 AM

selectgolangforhighpperformanceandcorrency,ifealforBackendServicesSandNetwork程序; selectpypypythonforrapiddevelopment,dataScience和machinelearningDuetoitsverserverserverserversator versator anderticality andextility andextentensivelibraries。

Golang vs. Python:主要差異和相似之處Golang vs. Python:主要差異和相似之處Apr 17, 2025 am 12:15 AM

Golang和Python各有优势:Golang适合高性能和并发编程,Python适用于数据科学和Web开发。Golang以其并发模型和高效性能著称,Python则以简洁语法和丰富库生态系统著称。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具