Golang 教學系列 - 何謂 Goroutine

從這邊文章開始我會把我在 YouTube 上的 Golang 教學影片來一一寫成文章來紀錄一下重點,如果有興趣的人想看更詳細的內容,可以直接看我的影片會更加清楚喔:Golang 教學系列 - 何謂 Goroutine

而這篇文章介紹的是 Golang 語言中的 Goroutine 的應用,Goroutine 的實現其實是透過協程 (Coroutine),而事實上有 Process,Thread,我是建議在學 Goroutine 之前可以先去看我之前寫的文章,介紹關於進程 (Process)、線程 (Thread)、協程 (Coroutine) 的概念講解

來看簡單的找質數應用

這個應用就是給你一個數字,找出小於這個數字所有質數有哪些

直接上程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
"fmt"
"time"
)

func main() {
num := 300000
start := time.Now()
for i := 1; i <= num; i++ {
if isPrime(i) {
fmt.Println(i)
}
}
end := time.Now()
fmt.Println(end.Unix() - start.Unix(), "seconds")
}

func isPrime(num int) bool {
if num == 1 {
return false
} else if num == 2 {
return true
} else {
for i := 2; i < num; i++ {
if num % i == 0 {
return false
}
}
return true
}
}

判斷質數的方式

讓我們先來看 func isPrime,這個函式是拿來告訴我們說丟進去的 num 是不是質數。

而這邊會先判斷 num == 1 or num ==2,如果 num == 1 就不算是質數,反之如果 num = 2 就是質數。而當這兩個判斷都不是之後,就透過一個 for loop 去找出從 2~ < num 之間 有沒有數字可以整除這個 num,如果找的到就肯定該數字不是質數。

來看主程式

假設用 num := 300000 來測試,也就是從 1~300000 之間來看那些數字會是質數,如果是質數的話就把質數輸出,然後這邊順便用 time package 來做時間的計算,來看出會花多少秒。

這邊實際運行的會花至少好幾秒才可以將範圍內的質數找出來。

如何使用 Goroutine 來改善速度

直接看程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import (
"fmt"
"time"
)

func main() {
num := 300000
for i := 1; i <= num; i++ {
go findPrimes(i)
}
time.Sleep(5 * time.Second)
}

func findPrimes(num int) {
if num == 1 {
return
} else if num == 2 {
fmt.Println(num)
} else {
for i := 2; i < num; i++ {
if num % i == 0 {
return
}
}
fmt.Println(num)
}
}

找出所有質數

透過定義一個函式為 findPrimes(num int),來找出 num 是不是質數並輸出,一樣 1 or 2 可以先判斷,否則一樣透過一個 for loop 來找出 < num 有哪些質數。

這邊我事後看了一下影片發現這個函式的名稱取得不是很好 XD 理論上這個函式就是判斷 num 是不是質數,是的話就輸出這樣。

來看主程式

一樣以 num := 300000 來做示範,而這邊特別的是我們透過一個 for loop 去取出 1 ~ 300000 之間的每一個數字,透過 keyword: go 去對 findPrimes 函式來做操作,只要利用 go 這個關鍵字就可以開啟一個 Goroutine,因此以主程式來說這樣等於是開啟 300000 個 Goroutine 來各自判斷自己拿到 num 是不是質數這樣。

而在下方我們用 time.Sleep 來休息五秒來讓 main 主程式不要被關閉,否則由於開啟 Goroutine 之後程式碼會繼續往下執行,如果沒做 sleep 的話會導致主程式關閉,主程式一關閉 Goroutine 就跟著關閉了,我們就看不出效果了。

這邊運行之後會發現輸出的質數出現並不是從小到大的,這是因為這些 Goroutine 是一起做事情的,所以誰先做完誰就先輸出這樣。

而這邊也可以發現五秒內就可以做完了,跟第一個沒用 Goroutine 的程式可以發現速度上大幅的提升了。

總結

那這樣可能會覺得有一個小問題,那就是我怎麼知道我的 time.sleep 要休息幾秒?有沒有其他方式可以去等待 Goroutine 做完事情再讓我們的 main 主程式結束。畢竟使用 time.Sleep 是很不方便的,因此下一篇文章我們就會介紹如何透過 sync package 的 WaitGroup 來達到這種功能!

最後最後!請聽我一言!

如果你還沒有註冊 Like Coin,你可以透過我的邀請註冊連結來免費註冊,註冊完後就可以在文章最下方幫我按下 Like 按鈕,而 Like 最多可以點五次,如何一來你不用付出任何一塊錢,就能給我寫這篇文章最大的回饋!