iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Modern Web

golang後端入門分享系列 第 17

Day17-Goroutine

前言

goroutine 是 Go 語言實現併發的一種方式,在執行的過程需要少量的記憶體用量(4k~5k),以暫存自己的上下文,可在不同的時間點來分段執行程式。而 Go 語言也實作了 goroutine 之間的記憶體共用機制,並且設計了 channel 讓 goroutine 之間可以進行資料溝通。

goroutine使用

Go 語言在使用 goroutine 上非常簡單,只要函式前加個 go 即可。我們用 Go Tutorial 上的例子,然後先改編一下,試試看不要加 time.Sleep 看看(程式碼執行到 time.Sleep 時,會停頓指定的時間)。

package main
 
import (
   "fmt"
)
 
func say(s string) {
   for i := 0; i < 5; i++ {
       fmt.Println(s)
   }
}
 
func main() {
   go say("world")
   say("hello")
}

在執行程式碼後,會發現 goroutine 後的程式碼並沒有執行,這是因為你的主程式並沒有等你的 goroutine 執行,就結束掉了,所以我們必須要讓程式停頓一下,讓他可以執行 goroutine :

package main
 
import (
   "fmt"
   "time"
)
 
func say(s string) {
   for i := 0; i < 5; i++ {
       time.Sleep(100 * time.Millisecond)
       fmt.Println(s)
   }
}
 
func main() {
   go say("world")
   say("hello")
}

goroutine 搭配 sync.WaitGroup

在上一個例子,我們用讓程式碼睡一下的方法,使得併發得以實現,但在實務上,比較少直接使用這個方法,這裏要介紹另外一個方法,是使用 sync 套件裡的方法 WaitGroup,來實現併發:

package main
 
import (
   "fmt"
   "sync"
)
 
var wg sync.WaitGroup
 
func count(s string) {
   fmt.Println(s)
   wg.Done()
}
 
func main() {
   wg.Add(5)
   go count("1")
   go count("2")
   go count("3")
   go count("4")
   go count("5")
   wg.Wait()
}

我們來解以上的程式碼,在程式碼尾端加上wg.Wait(),讓他達成一些條件,才可以往後執行,而這個條件,就是收到wg.Done()的呼叫次數,而這個次數,即是wg.Add(5)裡的數字5,取決於你要執行幾個 goroutine,請確保這個數字要正確。

goroutine 搭配 channel

這裡要介紹 goroutine 與 channel 的搭配,channel 實現了 goroutine 之間進行資料溝通,而因為也有阻塞的特性,使其可以當作等待 goroutine 的方法,這也算是最平凡的用法之一,goroutine 與 channel 真的是 Go 語言妙的設計之一。

package main
 
import (
   "fmt"
   "time"
)
 
func say(s string, c chan string) {
   for i := 0; i < 5; i++ {
       time.Sleep(time.Second)
       fmt.Println(s)
   }
   c <- "FINISH"
}
 
func main() {
   ch := make(chan string)
 
   go say("world", ch)
   go say("hello", ch)
 
   <-ch
   <-ch
}

這裡起了兩個 goroutine,因此需要等待兩個 FINISH 推入 channel 中才能結束主程式的 goroutine。

結語

今天介紹了基本 goroutine 的使用方法,讀者們可以試著執行或是改編看看。而 goroutine 及 channel 簡單而強大的語法,使工程師便於開發又易於維護,是 Go 語言的優勢之一。感謝您今天的閱讀,希望有幫助到您!


上一篇
Day16-打包自己的 Go package
下一篇
Day18-Go錯誤處理(上)
系列文
golang後端入門分享30

尚未有邦友留言

立即登入留言