golanggoroutine是Go語言中的一種並發機制,它可以讓程序員通過輕量級線程(或稱協程)來編寫高效的並發程序。Go語言因此變得越來越受到程序員的青睞,尤其在分佈式系統、網絡編程、高並發場景下表現極為出色。
一、讓並發變得更加簡單
相比於其他編程語言來說,golanggoroutine是一種受歡迎的並發解決方案,最初設計初衷就是讓並發編程變得更簡單,更易於上手。以往,程序員需要手動創建線程,並在其中使用鎖來避免資源競爭導致的問題。這是一項相對困難的任務,而且還容易出錯。
在Go中,golanggoroutine是一種輕量級的線程,Go語言運行時(runtime)會在適當的時候將goroutine調度到不同的線程中執行。而這一切都是由Go語言運行時管理的,對於使用者來說,只需要將程序模塊打包成golanggoroutine,就可以更方便地進行並發編程。
下面是樣例代碼:
func countNumbers() { for i := 1; i < 10; i++ { fmt.Println(i) time.Sleep(time.Millisecond * 500) } } func countCharacters() { for char := 'a'; char <= 'z'; char++ { fmt.Printf("%c ", char) time.Sleep(time.Millisecond * 500) } } func main() { go countNumbers() go countCharacters() time.Sleep(time.Second * 5) fmt.Println("Done") }
在上面的代碼示例中,countNumbers和countCharacters分別代表了兩個goroutine。調用go關鍵字可以輕鬆地實現並發執行兩個goroutine的操作。可以看到,相比於其他語言的線程實現,代碼的編寫量要少得多。並且,使用goroutine也可以避免對鎖的依賴,使得程序不容易出現死鎖等問題。
二、啟動goroutine
啟動goroutine非常簡單,只需要在函數調用前加上關鍵詞go即可。Go語言運行時會啟動一個新的goroutine,函數也會在獨立的goroutine中運行。
下面是樣例代碼:
package main import ( "fmt" ) func worker() { fmt.Println("Worker") } func main() { go worker() fmt.Println("Main") // sleep to show output time.Sleep(time.Second) }
在上面的代碼示例中,可以看到,在worker函數調用前,加了go關鍵字。在程序運行時,worker函數將會在獨立的goroutine中執行,和main函數同時運行。可以看到,在console中打印出了Worker和Main兩個字符串。
三、goroutine中使用channel進行通信
除了使用goroutine外,Go語言中的另一個重要特性是channel。channel是一種數據類型,用於在不同的goroutine之間傳遞消息。
下面是樣例代碼:
package main import ( "fmt" ) func main() { ch := make(chan int) go func() { ch <- 1 ch <- 2 ch <- 3 ch <- 4 close(ch) }() for n := range ch { fmt.Println(n) } }
在上面的代碼示例中,使用make函數創建了一個整數類型的channel。啟動一個goroutine並將整數類型的值1-4寫入channel中,最後關閉channel。在主函數中,使用for循環和range迭代器接收channel中的值,然後將它們打印到控制台中。
四、使用select語句管理channel
select語句使 goroutine 執行期間可以等待多個channel 上的事件。select語句的響應方式類似於switch語句,它會等待其中之一條件成立時執行對應的語句塊。
下面是樣例代碼:
package main import ( "fmt" "time" ) func worker1(messages chan string) { for i := 0; ; i++ { messages <- "worker1: " + fmt.Sprintf("%d", i) time.Sleep(time.Second) } } func worker2(messages chan string) { for i := 0; ; i++ { messages <- "worker2: " + fmt.Sprintf("%d", i) time.Sleep(time.Second * 2) } } func main() { messages := make(chan string) go worker1(messages) go worker2(messages) for { select { case message1 := <-messages: fmt.Println(message1) case message2 := <-messages: fmt.Println(message2) case <-time.After(time.Second * 5): fmt.Println("timeout") return } } }
在上面的代碼示例中,啟動了兩個goroutine。使用make函數創建一個通道,並將兩個goroutine中的結果寫入該通道。主函數中使用select語句等待message1和message2從通道messages上被同時接收到。其中第三個case用time.After模擬5秒超時,當這個case被選擇時,程序將結束並退出。
五、golanggoroutine的性能
由於goroutine是輕量級線程,創建和銷毀時開銷都非常小,所以它們可以被迅速地創建和銷毀。此外,Go語言運行時在多個goroutine之間進行智能調度,可以讓多個goroutine在單個或少量線程上並發運行,不會出現線程的頻繁切換帶來的性能開銷。
下面是樣例代碼:
package main import "fmt" func sum(a []int, c chan int) { sum := 0 for _, v := range a { sum += v } c <- sum } func main() { a := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(a[:len(a)/2], c) go sum(a[len(a)/2:], c) x, y := <-c, <-c fmt.Println(x, y, x+y) }
在上面的代碼示例中,採用了兩個goroutine進行數組的並行求和。在最終結果被求出的時候,只需要進行一次channel的讀取操作,使得程序具有比較快的運行速度。
結語
golanggoroutine是Go語言中的一種重要並發機制,該特性具有輕量、簡單、易用、性能高等優點。在分佈式系統、網絡編程、高並發場景下表現尤為突出。藉助於goroutine和channel, Go語言可以更加容易地實現並發編程。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/196165.html