GoRoutines高性能同時進行多個Api調(diào)用實現(xiàn)
正文
Golang是高效的,非常高效。這種效率在很大程度上要歸功于它在處理并發(fā)性問題時的獨特抽象。例如,Java將其線程映射為操作系統(tǒng)線程,而Go使用自己的goroutines調(diào)度器將其輕量級goroutines從操作系統(tǒng)線程中進一步抽象出來。簡而言之,Golang在使用操作系統(tǒng)線程方面非常節(jié)儉;如果一個goroutine被阻塞了,Go的調(diào)度器會在它的位置上切換另一個goroutine,以盡可能地保持線程的忙碌。由于每個CPU核心處理的線程數(shù)量有限(而且產(chǎn)生新的線程是很昂貴的),保持這些線程的工作是一件很好的事情。
那么,我們?nèi)绾问褂肎olang來并發(fā)地進行多個http調(diào)用呢?如果你使用過C#或現(xiàn)代JavaScript,你可能使用過async/await來進行多個api調(diào)用。Golang并不那么容易,但這都是以效率為名義的。Go總是至少有一個goroutine在運行,它負責運行main()。我們可以在函數(shù)調(diào)用前用關(guān)鍵字go催生新的例程。如果你從事過Java/C#的異步調(diào)用,那么goroutine可能會讓你想起上下文的概念。[文章來源:janrs.com] Go Scheduler允許開發(fā)者制作成千上萬個這種輕量級的goroutines,并為我們管理每個goroutines所花費的CPU時間。每當一個以go為前綴的函數(shù)被執(zhí)行時,就會創(chuàng)建一個新的goroutine來運行該函數(shù),主goroutine在生成一個新的goroutine后立即繼續(xù)前進,直到它遇到一個阻塞操作符(類似于C#或Js中的await)。
原始調(diào)用
讓我們從一個簡單的控制臺應(yīng)用開始,它調(diào)用了幾個GitHub配置文件,并檢查連接是否成功。起初,這里沒有g(shù)oroutines,所有的調(diào)用都是連續(xù)進行的,效率不高。
// 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)用
首先,我們需要添加一個叫做通道的東西。由于在自己的goroutine中運行的Golang函數(shù)只是簡單的函數(shù),我們需要一種方法,通過它內(nèi)部的goroutine可以把它們的結(jié)果告訴外部的goroutine;這就是使用通道來實現(xiàn)的。我們通過以下方式初始化它們: c := make(chan string) 我們能夠使用<- 箭頭將結(jié)果值發(fā)送到我們的通道,我們也可以使用這個箭頭將通道的值分配出去。
第二,我們需要添加一個跟 蹤 器,來跟蹤我們應(yīng)該期待多少個值從這個通道出來。這可以通過使用sync.WaitGroup.WaitGroup的類型來完成。
落實這兩個想法,代碼如下。
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)在這里有一個待處理的操作。 go checkUrl(link, c, &wg) } go func() { wg.Wait() // 這將阻止Goroutine,直到WaitGroup計數(shù)器為零。#janrs.com close(c) // 通道需要被關(guān)閉,否則下面的循環(huán)將永遠持續(xù)下去 }() // 這個簡略的循環(huán)是一個無休止的循環(huán)的語法糖,它只是在等待結(jié)果通過'c'通道進入。 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高性能同時進行多個Api調(diào)用實現(xiàn)的詳細內(nèi)容,更多關(guān)于GoRoutines多個Api同時調(diào)用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang在整潔架構(gòu)基礎(chǔ)上實現(xiàn)事務(wù)操作
這篇文章在 go-kratos 官方的 layout 項目的整潔架構(gòu)基礎(chǔ)上,實現(xiàn)優(yōu)雅的數(shù)據(jù)庫事務(wù)操作,需要的朋友可以參考下2024-08-08golang struct, map, json之間的相互轉(zhuǎn)換
本文用于記錄我在 golang 學習階段遇到的類型轉(zhuǎn)換問題,針對的是 json 、map、struct 之間相互轉(zhuǎn)換的問題,感興趣的可以了解一下2021-06-06gorm+gin實現(xiàn)restful分頁接口的實踐
本文主要介紹了gorm+gin實現(xiàn)restful分頁接口的實踐,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12