基礎概念的部份到此結束,接下來就比較偏向講解語言特色以及Package的使用與概念,今天的主題是Goroutine,是Go語言的並發處理的核心機制。因為我是第一次接觸這個概念,所以可能不會講得很深入,但我會盡量讓大家了解這個概念。
Go語言以其內建的並發處理能力著稱,其中最具代表性的功能就是Goroutine。
Goroutine是Go語言實現並發處理的核心機制,本質上是一個輕量級的執行緒(Thread)。由Runtime管理,可以在一個OS執行緒上同時運行多個Goroutine,而不需要額外的程式碼來管理。與傳統的執行緒相比,Goroutine的優勢在於其低成本的創建和管理,以及自動伸縮的stack大小(從2KB開始,最大可達1GB)使得資源消耗更具彈性。
以Java 8為例,執行一個Thread 預設需要分配1MB 記憶體,而Golang只需要2kB 範例程式
除此之外,你可以把任何函數都變成Goroutine來執行,只需要在呼叫函數前加上 go
關鍵字即可。這樣就可以讓函數在背景執行,不會阻塞主程式的執行。(類似於你在Linux shell中透過&
符號讓指令在背景執行)
package main
import (
"fmt"
"time"
)
const (
_ = 2 << (10 * iota)
GiB
)
func sayHelloWithSize(size int) {
fmt.Println("Hello, Goroutine!", size)
}
func main() {
go sayHelloWithSize(GiB)
fmt.Println("Gonna Say~~ GoodBye")
}
怎麼沒有Print出結果?
以我們的程式來說,造成這個bug的原因其實是因為主程式在啟動Goroutine後就立即結束了,而Goroutine並不會阻止主程式的結束。而是跟著主程式一起隨風而去。因此為了讓主程式等待Goroutine執行完畢,最簡單的方式是使用time.Sleep()
函數來暫停主程式的執行,讓Goroutine有足夠的時間執行。
package main
import (
"fmt"
"time"
)
const (
_ = 2 << (10 * iota)
KiB
)
func sayHelloWithSize(size int) {
fmt.Println("Hello, Goroutine!", size)
}
func main() {
go sayHelloWithSize(KiB)
time.Sleep(2 * time.Second)
fmt.Println("Gonna Say~~ GoodBye")
}
有時候我們想要在程式中即時定義Goroutine,但又不想額外定義函數。在這種情況下,可以透過go func() { ... }()
的方式來執行匿名函數。
package main
import (
"fmt"
"time"
)
func main() {
go func() {
fmt.Println("Hello from anonymous Goroutine!")
}()
time.Sleep(1 * time.Second)
fmt.Println("Main function finished.")
}
這段程式碼直接將匿名函數作為Goroutine執行,這樣可以避免定義過多的小函數。
你也可以在同一個程式中同時執行多個Goroutine以提昇效率
注意: 最多不可超過1048576個平行運算同時執行
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < (1 << 16); i++ {
go func(i int) {
fmt.Println("Hello from anonymous Goroutine!", i)
}(i)
}
time.sleep(4 * time.Second)
fmt.Println("Gonna Say~~ GoodBye")
}
那麼今天的文章就到這告一段落,如果我的文章有任何地方有錯誤請在留言區反應
明天將會介紹Go語言的Channel介紹與使用