Go語言中goroutine的使用
一、什么是 Goroutine ?
在java/c++中我們要實現(xiàn)并發(fā)編程的時候,我們通常需要自己維護一個線程池,并且需要自己去包裝一個又一個的任務,同時需要自己去調度線程執(zhí)行任務并維護上下文切換,這一切通常會耗費程序員大量的心智。那么能不能有一種機制,程序員只需要定義很多個任務,讓系統(tǒng)去幫助我們把這些任務分配到CPU上實現(xiàn)并發(fā)執(zhí)行呢?
Go語言中的goroutine就是這樣一種機制,goroutine的概念類似于線程,但 goroutine是由Go的運行時(runtime)調度和管理的。Go程序會智能地將 goroutine 中的任務合理地分配給每個CPU。Go語言之所以被稱為現(xiàn)代化的編程語言,就是因為它在語言層面已經內置了調度和上下文切換的機制。
在Go語言編程中你不需要去自己寫進程、線程、協(xié)程,你的技能包里只有一個技能–goroutine,當你需要讓某個任務并發(fā)執(zhí)行的時候,你只需要把這個任務包裝成一個函數(shù),開啟一個goroutine去執(zhí)行這個函數(shù)就可以了,就是這么簡單粗暴。
二、使用 Goroutine
Go語言中使用goroutine非常簡單,只需要在調用函數(shù)的時候在前面加上go關鍵字,就可以為一個函數(shù)創(chuàng)建一個goroutine。
一個goroutine必定對應一個函數(shù),可以創(chuàng)建多個goroutine去執(zhí)行相同的函數(shù)。
單個 goroutine
package main
import "fmt"
func hello() {
fmt.Println("Hello Goroutine!")
}
func main() {
go hello()
fmt.Println("main goroutine done!")
}執(zhí)行這段程序:
main goroutine done!
那么問題來了:為什么 Hello Goroutine! 沒有輸出呢?
在程序啟動時,Go程序就會為main()函數(shù)創(chuàng)建一個默認的goroutine。
當main()函數(shù)返回的時候該goroutine就結束了,所以在main()函數(shù)中啟動的goroutine會一同結束,main函數(shù)所在的goroutine就像是權利的游戲中的夜王,其他的goroutine都是異鬼,夜王一死它轉化的那些異鬼也就全部GG了。
所以咱們要想辦法讓main函數(shù)等一等hello函數(shù),最簡單粗暴的方式就是time.Sleep了。
示例:
package main
import "fmt"
func hello() {
fmt.Println("Hello Goroutine!")
}
func main() {
go hello()
fmt.Println("main goroutine done!")
time.Sleep(time.Second) // 等待1秒
}執(zhí)行這段程序:
Hello Goroutine!
main goroutine done!
多個 goroutine
package main
import "fmt"
func hello() {
fmt.Println("Hello Goroutine!")
}
func word() {
fmt.Println("Word Goroutine!")
}
func main() {
go hello()
go word()
fmt.Println("main goroutine done!")
time.Sleep(2 * time.Second) // 等待2秒
}執(zhí)行這段程序:
Hello Goroutine!
Word Goroutine!
main goroutine done!
開啟多個 goroutine 只需要再使用一次go關鍵字就可以了。
同樣的,咱們?yōu)榱俗屗軌蛲暾敵?,使?time.Sleep 讓main函數(shù)等待 goroutine 執(zhí)行完成。
sync.WaitGroup 的使用
上面咱們講了如何開啟goroutine,為了goroutine正常輸出,增加了 time.Sleep 等待。
但在我們實際項目開發(fā)中,生硬的使用time.Sleep肯定是不合適的。那我們應該如何才能正確優(yōu)雅的讓 main 函數(shù)等待 goroutine 執(zhí)行完之后再執(zhí)行呢?
go語言提供了一個 sync.WaitGroup 的一個計數(shù)器的功能??梢杂脕韮?yōu)雅的實現(xiàn) goroutine 的正常執(zhí)行和 main 函數(shù)的等待。
示例:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func hello(){
defer wg.done() // 計數(shù)器 - 1
fmt.Println("Hello Goroutine!")
}
func main(){
wg.Add(1) // 計數(shù)器 + 1
go hello()
wg.wait() // 阻塞直到計數(shù)器變?yōu)?
fmt.Println("main goroutine done!")
}執(zhí)行這段程序:
Hello Goroutine!
main goroutine done!
| 方法名 | 功能 |
|---|---|
| (wg * WaitGroup) Add(delta int) | 計數(shù)器+delta |
| (wg *WaitGroup) Done() | 計數(shù)器-1 |
| (wg *WaitGroup) Wait() | 阻塞直到計數(shù)器變?yōu)? |
sync.WaitGroup內部維護著一個計數(shù)器,計數(shù)器的值可以增加和減少。例如當我們啟動了 N 個并發(fā)任務時,就將計數(shù)器值增加N。每個任務完成時通過調用Done()方法將計數(shù)器減1。通過調用Wait()來等待并發(fā)任務執(zhí)行完,當計數(shù)器值為0時,表示所有并發(fā)任務已經完成。
在實際項目中使用sync.WaitGroup 可以更好的、更優(yōu)雅的控制goroutine。
三. 結束語
到此這篇關于Go語言中goroutine的使用的文章就介紹到這了,更多相關Go語言goroutine內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
VsCode搭建Go語言開發(fā)環(huán)境的配置教程
這篇文章主要介紹了在VsCode中搭建Go開發(fā)環(huán)境的配置教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05
go 迭代string數(shù)組操作 go for string[]
這篇文章主要介紹了go 迭代string數(shù)組操作 go for string[],具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Go語言中的圖形界面開發(fā)從GUI到WebAssembly示例詳解
圖形界面是現(xiàn)代應用的重要組成部分,它為用戶提供了直觀、交互性強的操作方式,這篇文章主要介紹了Go語言中圖形界面開發(fā)從GUI到WebAssembly的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2026-05-05
Golang通過SSH執(zhí)行交換機操作實現(xiàn)
這篇文章主要介紹了Golang通過SSH執(zhí)行交換機操作實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06
go語言開發(fā)環(huán)境配置(sublime text3+gosublime)
網上google了下go的開發(fā)工具,大都推薦sublime text3+gosublime,本文就介紹了go語言開發(fā)環(huán)境配置(sublime text3+gosublime),具有一定的參考價值,感興趣的可以了解一下2022-01-01
GoLang jwt無感刷新與SSO單點登錄限制解除方法詳解
這篇文章主要介紹了GoLang jwt無感刷新與SSO單點登錄限制解除方法,JWT是一個簽名的JSON對象,通常用作Oauth2的Bearer token,JWT包括三個用.分割的部分。本文將利用JWT進行認證和加密,感興趣的可以了解一下2023-03-03

