提升應(yīng)用性能:Go中的同步與異步處理
在開發(fā)過程中,當(dāng)需要同時(shí)處理多個(gè)操作時(shí),開發(fā)者經(jīng)常面臨同步和異步兩種處理方式的選擇。
同步處理
在同步處理方式中,任務(wù)按順序一個(gè)接一個(gè)地執(zhí)行。每個(gè)任務(wù)必須在下一個(gè)任務(wù)開始之前完成。這意味著如果某個(gè)任務(wù)需要花費(fèi)大量時(shí)間來完成,它可能會(huì)阻塞后續(xù)任務(wù)的執(zhí)行,導(dǎo)致潛在的性能瓶頸。
一個(gè)簡單的現(xiàn)實(shí)生活中的例子是兩個(gè)人在喝啤酒時(shí)進(jìn)行對話。一個(gè)人說一些話并提問,另一個(gè)人根據(jù)情況回應(yīng),然后反過來...
在下面的示例中,每個(gè)URL調(diào)用必須完成其整個(gè)請求-響應(yīng)周期并提供響應(yīng)或錯(cuò)誤,以便可以進(jìn)行后續(xù)的URL調(diào)用。
package main
import (
"fmt"
"net/http"
)
func makeUrlCall(url string) {
_, err := http.Get(url)
if err != nil {
fmt.Println("Got error in connecting to url: ", url)
}
fmt.Println("Got the response from our url: ", url)
}
func main() {
fmt.Println("Welcome here !!")
fmt.Println()
//slice of urls
urlSlice := []string{
"https://www.baidu.com",
"https://www.csdn.net",
"https://www.runoob.com",
}
for idx, url := range urlSlice {
fmt.Println("Calling url on index: ", idx)
makeUrlCall(url)
}
fmt.Println()
fmt.Println("End of sync processing !!")
return
}
輸出:
Welcome here !!
Calling url on index: 0
Got the response from our url: https://www.baidu.com
Calling url on index: 1
Got the response from our url: https://www.csdn.net
Calling url on index: 2
Got the response from our url: https://www.runoob.com
End of sync processing !!
異步處理
在異步處理方式中,任務(wù)獨(dú)立并同時(shí)執(zhí)行。這意味著程序在一個(gè)任務(wù)完成之前不會(huì)等待它繼續(xù)下一個(gè)任務(wù)。在Golang中,可以使用Goroutines和Go運(yùn)行時(shí)來實(shí)現(xiàn)異步編程。
一個(gè)簡單的現(xiàn)實(shí)生活中的例子是去汽車修理店。一旦工程師處理完其他任務(wù),他們會(huì)處理你的任務(wù)。在此期間,你可以做其他重要的事情,直到你的汽車被取走并修好。
在下面的示例中,每個(gè)URL調(diào)用將通過goroutine在自己的線程中進(jìn)行,并根據(jù)需要處理響應(yīng)。
package main
import (
"fmt"
"net/http"
"sync"
)
func makeUrlCall(url string) {
_, err := http.Get(url)
if err != nil {
fmt.Println("Got error in connecting to url: ", url)
}
fmt.Println("Got the response from our url: ", url)
}
func main() {
fmt.Println("Welcome here !!")
fmt.Println()
//slice of urls
urlSlice := []string{
"https://www.baidu.com",
"https://www.csdn.net",
"https://www.runoob.com",
}
var wg sync.WaitGroup
for _, u := range urlSlice {
wg.Add(1)
//all the url's to get error/response are called in their own separate thread via goroutines
go func(url string) {
defer wg.Done()
makeUrlCall(url)
}(u)
}
wg.Wait()
fmt.Println()
fmt.Println("End of sync processing !!")
return
}
輸出:
Welcome here !!
Got the response from our url: https://www.baidu.com
Got the response from our url: https://www.runoob.com
Got the response from our url: https://www.csdn.net
End of sync processing !!
如果我們在切片中添加更多的URL并進(jìn)行更多的HTTP get請求,比較兩種方式的性能。