Goroutinesってなに?
educativeには、以下のように書いてあります。
ゴルーチンとは、Goプログラミング言語における軽量の実行スレッドであり、プログラムの他の部分と同時に実行される関数です。
ゴルーチンは、従来のスレッドと比較すると、ゴルーチンを作成するオーバーヘッドが非常に小さいため、驚くほど安価です。そのため、Goでは並行プログラミングに広く使われています。
関数をgoroutineとして呼び出すには、goキーワードを使用します。
なるほど、わからん。まぁとりあえず、 同時に実行される ということですね。
コードのテンプレート
2つの関数 heyko1() と heyko2() が同時に実行される(並行処理される)ための関数 main() を作成します。
goroutinesを呼び出すときには、基本的には呼び出すところで関数の前にgoをつけることで並行処理として利用できます。これだけで並行処理にできるというところがgoのいいところなんです。
まず、基本的に以下のような形で書きました。
func main() {
// 普通の処理(同期処理)
normalFunc()
// 並行処理(goroutinesとして呼び出す)
go parallelFunc()
}
goをつけるかつけないかだけです。
次に、関数を2つ作り、並行処理を簡単に実装してみます。
package main
import (
"fmt"
"sync"
)
// heyko1 はgoroutineで実行する最初の関数です。
func heyko1(wg *sync.WaitGroup) {
defer wg.Done() // 関数終了時にWaitGroupのカウントをデクリメント
// ここにheyko1の処理を書きます
fmt.Println("heyko1 の実行中です")
}
// heyko2 はgoroutineで実行する2番目の関数です。
func heyko2(wg *sync.WaitGroup) {
defer wg.Done() // 関数終了時にWaitGroupのカウントをデクリメント
// ここにfunction2の処理を書きます
fmt.Println("heyko2 の実行中です")
}
func main() {
var wg sync.WaitGroup // WaitGroupの初期化
wg.Add(2) // WaitGroupのカウントを2つのgoroutineの数だけインクリメント
go heyko1(&wg) // heyko1をgoroutineとして実行
go heyko2(&wg) // heyko2をgoroutineとして実行
wg.Wait() // すべてのgoroutineの終了を待機
fmt.Println("全て終了")
}
基本的にこのような形になります。これらを実際に時間の処理を入れてみましょう。
package main
import (
"fmt"
"sync"
"time"
)
func main() {
fmt.Println("はじまり〜")
var wg sync.WaitGroup
// WaitGroupのカウンタを2つ増やす
wg.Add(2)
// process1をgoroutineとして実行
go func() {
heyko1()
defer wg.Done() // 処理が完了したらWaitGroupのカウンタを減らす
}()
// process2をgoroutineとして実行
go func() {
heyko2()
defer wg.Done() // 処理が完了したらWaitGroupのカウンタを減らす
}()
// すべてのgoroutineが終了するのを待つ
wg.Wait()
fmt.Println("おわり〜")
}
func heyko1() {
start := time.Now()
time.Sleep(10 * time.Second)
end := time.Now()
fmt.Println("heyko1: ", (end.Sub(start)).Seconds())
fmt.Println("heyko1: ", start.Format("2006-01-02T15:04:05Z07:00"), "~~", end.Format("2006-01-02T15:04:05Z07:00"))
}
func heyko2() {
start := time.Now()
end := time.Now()
fmt.Println("heyko2: ", (end.Sub(start)).Seconds())
fmt.Println("heyko2: ", start.Format("2006-01-02T15:04:05Z07:00"), "~~", end.Format("2006-01-02T15:04:05Z07:00"))
}
↓ 実行結果
はじまり〜
heyko2: 1.27e-07
heyko2: 2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:07+09:00
heyko1: 10.000868864
heyko1: 2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:17+09:00
おわり〜
なぜ時間で書いたかというと、heyko1とheyko2の始まるタイミングと終わるタイミングが同じであり、処理時間が違うため、終了時間が異なることを確認するためです。
実際に
heyko2: 2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:07+09:00
heyko1: 2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:17+09:00
となっているため、始まりは一緒の2024-02-23T16:13:07+09:00 です。
そのあとは、10秒の差があって、終わっています。
実体験で感じれましたね!
以上!