1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

Go言語:ゴルーチンの完全な終了を確実にする方法

Posted at

はじめに

Go言語では、非同期のタスクを実行するための手段としてゴルーチンを利用することが一般的です。
しかしながら、その利用には注意が必要です。今回はその一つ、main関数が終了すると共にゴルーチンも終了してしまう問題とその解決策について記載します。

ゴルーチンとmain関数の関係性

まずは以下のゴルーチンが含まれたコードを見てみましょう。

package main

import (
	"fmt"
)

func sayHello() {
	fmt.Println("Hello")
}

func sayWorld() {
	fmt.Println("World")
}

func main() {
	go sayHello()
	go sayWorld()
}

このコードでは、main関数がsayHellosayWorldのゴルーチンを起動します。
しかし、ここには一つ問題があります。それは、main関数が終了すると全てのゴルーチンも終了するというGoの特性上、これらのゴルーチンが終了する前にmain関数が終了してしまい、ゴルーチンが完全に実行されない可能性があるという点です。

暫定的な解決策:time.Sleep

この問題を解決する一つの方法として、main関数の終了を遅らせるtime.Sleep関数を使用することが考えられます。

package main

import (
	"fmt"
	"time"
)

func sayHello() {
	fmt.Println("Hello")
}

func sayWorld() {
	fmt.Println("World")
}

func main() {
	go sayHello()
	go sayWorld()

	// Wait for the goroutines to finish
	time.Sleep(time.Second)
}

しかしこの解決策は一時的なものであり、正確なゴルーチンの終了タイミングを保証するものではないため、実際のプログラムでは推奨されません。

正確なゴルーチンの終了管理:sync.WaitGroup

ゴルーチンの終了を管理する正しい方法は、チャネルやsync.WaitGroupのような同期プリミティブを使用することです。特に、sync.WaitGroupは、複数のゴルーチンが終了するのを待つための簡便な方法として提供されています。

具体的には、sync.WaitGroupはカウンタを提供します。このカウンタは、Addメソッドで増やし、Doneメソッドで減らすことができます。そして、Waitメソッドはカウンタが0になるまで待ち続けます。

以下にその使用例を示します:

package main

import (
	"fmt"
	"sync"
)

func sayHello(wg *sync.WaitGroup) {
	fmt.Println("Hello")
	wg.Done() // Decrease counter
}

func sayWorld(wg *sync.WaitGroup) {
	fmt.Println("World")
	wg.Done() // Decrease counter
}

func main() {
	var wg sync.WaitGroup

	wg.Add(2) // Increase counter

	go sayHello(&wg)
	go sayWorld(&wg)

	wg.Wait() // Wait for counter to be 0
}

このコードでは、sync.WaitGroupを用いてsayHellosayWorldのゴルーチンが確実に終了することを保証しています。main関数はゴルーチンの起動前にカウンタを2に設定し、各ゴルーチンが終了した時点でカウンタを減らします。最後に、main関数は全てのゴルーチンが終了する(=カウンタが0になる)のを待ちます。

これにより、main関数はsayHellosayWorldのゴルーチンが確実に終了するのを待つことができます。特に、ゴルーチンが共有リソース(例えば、ファイルやデータベース接続)のクリーンアップを必要とする場合など、ゴルーチンの終了を待つ必要がある際に有用です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?