GoRoutines高性能同時(shí)進(jìn)行多個(gè)Api調(diào)用實(shí)現(xiàn)
正文
Golang是高效的,非常高效。這種效率在很大程度上要?dú)w功于它在處理并發(fā)性問題時(shí)的獨(dú)特抽象。例如,Java將其線程映射為操作系統(tǒng)線程,而Go使用自己的goroutines調(diào)度器將其輕量級(jí)goroutines從操作系統(tǒng)線程中進(jìn)一步抽象出來。簡(jiǎn)而言之,Golang在使用操作系統(tǒng)線程方面非常節(jié)儉;如果一個(gè)goroutine被阻塞了,Go的調(diào)度器會(huì)在它的位置上切換另一個(gè)goroutine,以盡可能地保持線程的忙碌。由于每個(gè)CPU核心處理的線程數(shù)量有限(而且產(chǎn)生新的線程是很昂貴的),保持這些線程的工作是一件很好的事情。
那么,我們?nèi)绾问褂肎olang來并發(fā)地進(jìn)行多個(gè)http調(diào)用呢?如果你使用過C#或現(xiàn)代JavaScript,你可能使用過async/await來進(jìn)行多個(gè)api調(diào)用。Golang并不那么容易,但這都是以效率為名義的。Go總是至少有一個(gè)goroutine在運(yùn)行,它負(fù)責(zé)運(yùn)行main()。我們可以在函數(shù)調(diào)用前用關(guān)鍵字go催生新的例程。如果你從事過Java/C#的異步調(diào)用,那么goroutine可能會(huì)讓你想起上下文的概念。[文章來源:janrs.com] Go Scheduler允許開發(fā)者制作成千上萬個(gè)這種輕量級(jí)的goroutines,并為我們管理每個(gè)goroutines所花費(fèi)的CPU時(shí)間。每當(dāng)一個(gè)以go為前綴的函數(shù)被執(zhí)行時(shí),就會(huì)創(chuàng)建一個(gè)新的goroutine來運(yùn)行該函數(shù),主goroutine在生成一個(gè)新的goroutine后立即繼續(xù)前進(jìn),直到它遇到一個(gè)阻塞操作符(類似于C#或Js中的await)。
原始調(diào)用
讓我們從一個(gè)簡(jiǎn)單的控制臺(tái)應(yīng)用開始,它調(diào)用了幾個(gè)GitHub配置文件,并檢查連接是否成功。起初,這里沒有g(shù)oroutines,所有的調(diào)用都是連續(xù)進(jìn)行的,效率不高。
// Auth: janrs.com package main import "fmt" import "net/http" func main() { links := []string{ "https://github.com/fabpot", "https://github.com/andrew", "https://github.com/taylorotwell", "https://github.com/egoist", "https://github.com/HugoGiraudel", } checkUrls(links) } func checkUrls(urls []string) { for _, link := range urls { checkUrl(link) } } func checkUrl(url string) { _, err := http.Get(url) if err != nil { fmt.Println("We could not reach:", url) } else { fmt.Println("Success reaching the website:", url) } }
高性能調(diào)用
首先,我們需要添加一個(gè)叫做通道的東西。由于在自己的goroutine中運(yùn)行的Golang函數(shù)只是簡(jiǎn)單的函數(shù),我們需要一種方法,通過它內(nèi)部的goroutine可以把它們的結(jié)果告訴外部的goroutine;這就是使用通道來實(shí)現(xiàn)的。我們通過以下方式初始化它們: c := make(chan string) 我們能夠使用<- 箭頭將結(jié)果值發(fā)送到我們的通道,我們也可以使用這個(gè)箭頭將通道的值分配出去。
第二,我們需要添加一個(gè)跟 蹤 器,來跟蹤我們應(yīng)該期待多少個(gè)值從這個(gè)通道出來。這可以通過使用sync.WaitGroup.WaitGroup的類型來完成。
落實(shí)這兩個(gè)想法,代碼如下。
import ( "fmt" "net/http" "sync" ) func main() { links := []string{ "https://github.com/fabpot", "https://github.com/andrew", "https://github.com/taylorotwell", "https://github.com/egoist", "https://github.com/HugoGiraudel", } checkUrls(links) } func checkUrls(urls []string) { c := make(chan string) var wg sync.WaitGroup for _, link := range urls { wg.Add(1) // 這告訴wg,現(xiàn)在這里有一個(gè)待處理的操作。 go checkUrl(link, c, &wg) } go func() { wg.Wait() // 這將阻止Goroutine,直到WaitGroup計(jì)數(shù)器為零。#janrs.com close(c) // 通道需要被關(guān)閉,否則下面的循環(huán)將永遠(yuǎn)持續(xù)下去 }() // 這個(gè)簡(jiǎn)略的循環(huán)是一個(gè)無休止的循環(huán)的語(yǔ)法糖,它只是在等待結(jié)果通過'c'通道進(jìn)入。 for msg := range c { fmt.Println(msg) } } func checkUrl(url string, c chan string, wg *sync.WaitGroup) { defer (*wg).Done() _, err := http.Get(url) if err != nil { c <- "#janrs.com#We could not reach:" + url // 將結(jié)果輸入通道 } else { c <- "Success reaching the website:" + url // 將結(jié)果輸入通道 } }
以上就是GoRoutines高性能同時(shí)進(jìn)行多個(gè)Api調(diào)用實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于GoRoutines多個(gè)Api同時(shí)調(diào)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Go語(yǔ)言Goroutines?泄漏場(chǎng)景與防治解決分析
- 盤點(diǎn)總結(jié)2023年Go并發(fā)庫(kù)有哪些變化
- Go語(yǔ)言單線程運(yùn)行也會(huì)有的并發(fā)問題解析
- Go并發(fā)原語(yǔ)之SingleFlight請(qǐng)求合并方法實(shí)例
- go并發(fā)數(shù)據(jù)一致性事務(wù)的保障面試應(yīng)答
- Go并發(fā)編程結(jié)構(gòu)體多字段原子操作示例詳解
- Go語(yǔ)言動(dòng)態(tài)并發(fā)控制sync.WaitGroup的靈活運(yùn)用示例詳解
- Go中Goroutines輕量級(jí)并發(fā)的特性及效率探究
相關(guān)文章
Golang在整潔架構(gòu)基礎(chǔ)上實(shí)現(xiàn)事務(wù)操作
這篇文章在 go-kratos 官方的 layout 項(xiàng)目的整潔架構(gòu)基礎(chǔ)上,實(shí)現(xiàn)優(yōu)雅的數(shù)據(jù)庫(kù)事務(wù)操作,需要的朋友可以參考下2024-08-08golang struct, map, json之間的相互轉(zhuǎn)換
本文用于記錄我在 golang 學(xué)習(xí)階段遇到的類型轉(zhuǎn)換問題,針對(duì)的是 json 、map、struct 之間相互轉(zhuǎn)換的問題,感興趣的可以了解一下2021-06-06gorm+gin實(shí)現(xiàn)restful分頁(yè)接口的實(shí)踐
本文主要介紹了gorm+gin實(shí)現(xiàn)restful分頁(yè)接口的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12golang多維度排序及題解最長(zhǎng)連續(xù)序列
這篇文章主要為大家介紹了golang多維度排序及題解最長(zhǎng)連續(xù)序列示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10Go Web下gin框架的模板渲染的實(shí)現(xiàn)
Gin框架是目前非常流行的Go語(yǔ)言Web框架之一,作為一個(gè)輕量級(jí)的框架,Gin提供了豐富的功能和靈活的架構(gòu),本文就來介紹下Go Web下gin框架的模板渲染的實(shí)現(xiàn),感興趣的可以了解一下2023-10-10