您好,登錄后才能下訂單哦!
這篇文章跟大家分析一下“go中的Golang協程怎么分析”。內容詳細易懂,對“go中的Golang協程怎么分析”感興趣的朋友可以跟著小編的思路慢慢深入來閱讀一下,希望閱讀后能夠對大家有所幫助。下面跟著小編一起深入學習“go中的Golang協程怎么分析”的知識吧。
1. Hello Goroutine
package main
import (
"fmt"
)
func main() {
go sayHello()
}
func sayHello() {
fmt.Println("Hello Goroutine !!!")
}
go語言開啟協程的關鍵詞是go,后面接著一個匿名函數或者一個自定義的函數,但是,如果運行了上面的代碼,你會發現終端并沒有輸出‘Hello Gorounitn !!!’,為什么呢?
上面的代碼并沒有問題,不會執行錯誤,之所以不會輸出是因為在golang語言中,main函數也是一個協程,而且是主協程。什么意思呢?就是每當你執行go項目時(必需有main函數,而且只能有一個main函數),會首先開啟一個main函數的主協程,這個主協程的執行時間會影響到子協程,子協程就是go關鍵詞加函數,如果主協程先執行完畢,那么子協程就不會被執行,所以 我把代碼改成這樣:
package main
import (
"fmt"
"time"
)
func main() {
go sayHello()
time.Sleep(time.Second)
}
func sayHello() {
fmt.Println("Hello Goroutine !!!")
}
輸出:
Hello Goroutine !!!
sleep 1s,等待子協程執行,所以會有輸出。
2. WaitGroup
等待子協程執行用睡眠的方式不符合實際開發,所以sync包下的WaitGroup可以解決這個問題,代碼:
package main
import (
"fmt"
"sync"
)
func main() {
wg := &sync.WaitGroup{}
wg.Add(2)
go sayHello(wg)
go sayHello2(wg)
wg.Wait()
}
func sayHello(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Hello Goroutine !!!")
}
func sayHello2(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Hello Golang !!!")
}
解釋:在main函數里聲明一個wg變量,wg.Add(2)的意思是我這里有兩個協程要執行,所以傳入2,如果你有n個協程呢?那就傳入n,wg.Done()相當與wg.Add(-1)就是該子協程執行完畢。wg.Wait()就是告訴主協程要等待子協程執行完畢才能退出。
3. Channel
channel,又叫管道,在go里面的管道是協程之間通信的渠道,類似于咱們常用的消息隊列。
package main
import (
"fmt"
"strconv"
)
func main() {
ch := make(chan string)
for i := 0; i <= 10; i++ {
go demo(ch, "Hello Channel"+strconv.Itoa(i))
}
for d := range ch {
fmt.Println(">>>>>>>>>>>>>>", d)
}
}
func demo(c chan string, data string) {
c <- data
}
簡單說明一下,這里就是實例化了一個string類型的管道,在調用函數的時候會把管道當作參數傳遞過去,然后在調用函數里面我們不輸出結果,然后把結果通過管道返還回去,然后再主線程里面我們通過for range循環依次取出結果!
但是這個程序是有bug的,在程序的運行的最后會出現一個fatal error,提示所有的協程都進入睡眠狀態,死鎖!
go的管道默認是阻塞的(假如你不設置緩存的話),你那邊放一個,我這頭才能取一個,如果你那邊放了東西這邊沒人取,程序就會一直等下去,死鎖了,同時,如果那邊沒人放東西,你這邊取也取不到,也會發生死鎖!
如何解決這個問題呢?標準的做法是主動關閉管道,或者你知道你應該什么時候關閉管道, 當然你結束程序管道自然也會關掉!針對上面的演示代碼,可以這樣寫:
var (
i int
)
for d := range ch {
fmt.Println(">>>>>>>>>>>>>>", d)
//
if i >= 10 {
close(ch)
}
i++
}
因為我們明確知道總共會輸出11個結果,所以這里簡單做了一個判斷,大于等于10就關閉管道退出for循環,就不會報錯了!雖然不是符合實際開發代碼規范,但是可以使用,能夠解釋原理。
golang是一種編譯語言,可以將代碼編譯為機器代碼,編譯后的二進制文件可以直接部署到目標機器而無需額外的依賴,所以golang的性能優于其他的解釋性語言,且可以在golang中使用goroutine來實現并發性,它提供了一個非常優雅的goroutine調度程序系統,可以很容易地生成數百萬個goroutine。
關于go中的Golang協程怎么分析就分享到這里啦,希望上述內容能夠讓大家有所提升。如果想要學習更多知識,請大家多多留意小編的更新。謝謝大家關注一下億速云網站!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。