目錄
並發請求介面的場景
goroutine並發處理
WaitGroup控制goroutine
並發請求的最佳實踐
總結
首頁 後端開發 Golang golang並發請求接口

golang並發請求接口

May 10, 2023 am 11:58 AM

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結束了—<-ch

二、避免請求阻塞

在進行並發請求介面的時候,我們需要避免請求阻塞,通常出現在一個請求長時間沒有對應時。我們可以使用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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1317
25
PHP教程
1268
29
C# 教程
1248
24
Golang vs. Python:性能和可伸縮性 Golang vs. Python:性能和可伸縮性 Apr 19, 2025 am 12:18 AM

Golang在性能和可擴展性方面優於Python。 1)Golang的編譯型特性和高效並發模型使其在高並發場景下表現出色。 2)Python作為解釋型語言,執行速度較慢,但通過工具如Cython可優化性能。

Golang和C:並發與原始速度 Golang和C:並發與原始速度 Apr 21, 2025 am 12:16 AM

Golang在並發性上優於C ,而C 在原始速度上優於Golang。 1)Golang通過goroutine和channel實現高效並發,適合處理大量並發任務。 2)C 通過編譯器優化和標準庫,提供接近硬件的高性能,適合需要極致優化的應用。

Golang的影響:速度,效率和簡單性 Golang的影響:速度,效率和簡單性 Apr 14, 2025 am 12:11 AM

goimpactsdevelopmentpositationality throughspeed,效率和模擬性。 1)速度:gocompilesquicklyandrunseff,IdealforlargeProjects.2)效率:效率:ITScomprehenSevestAndardArdardArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdEcceSteral Depentencies,增強的Depleflovelmentimency.3)簡單性。

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

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

Golang vs.C:性能和速度比較 Golang vs.C:性能和速度比較 Apr 21, 2025 am 12:13 AM

Golang適合快速開發和並發場景,C 適用於需要極致性能和低級控制的場景。 1)Golang通過垃圾回收和並發機制提升性能,適合高並發Web服務開發。 2)C 通過手動內存管理和編譯器優化達到極致性能,適用於嵌入式系統開發。

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

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

C和Golang:表演至關重要時 C和Golang:表演至關重要時 Apr 13, 2025 am 12:11 AM

C 更適合需要直接控制硬件資源和高性能優化的場景,而Golang更適合需要快速開發和高並發處理的場景。 1.C 的優勢在於其接近硬件的特性和高度的優化能力,適合遊戲開發等高性能需求。 2.Golang的優勢在於其簡潔的語法和天然的並發支持,適合高並發服務開發。

表演競賽:Golang vs.C 表演競賽:Golang vs.C Apr 16, 2025 am 12:07 AM

Golang和C 在性能競賽中的表現各有優勢:1)Golang適合高並發和快速開發,2)C 提供更高性能和細粒度控制。選擇應基於項目需求和團隊技術棧。

See all articles