Menu
Coddy logo textTech

Goroutine の基本

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 59/107。

goroutineは、Goランタイムによって管理される軽量な実行スレッドです。大量のメモリを消費する従来のスレッドとは異なり、goroutineはわずか数キロバイトのスタック領域で開始されるため、何千ものgoroutineをconcurrently実行できます。

goroutine を開始するには、関数呼び出しの前に go keyword を置くだけです:

func sayHello(name string) {
    fmt.Println("Hello,", name)
}

func main() {
    go sayHello("Alice")  // 並行して実行される
    go sayHello("Bob")    // 並行して実行される
    
    time.Sleep(100 * time.Millisecond)
    fmt.Println("Done")
}

go sayHello("Alice") が実行されると、sayHello の完了を待ちません。代わりに、sayHello がバックグラウンドで実行されている間、すぐに次の行へ進みます。これが time.Sleep が必要な理由です。これがないと、main は goroutines が完了する前に終了してしまいます。

無名関数を使ってgoroutineをlaunchすることもできます。

go func(msg string) {
    fmt.Println(msg)
}("Hello from goroutine")

main function 自体は goroutine 内で実行されます。main function が戻ると、他の goroutines はすべて直ちに終了します。完了する機会はありません。time.Sleep の使用は一時的な解決策です。これからのレッスンでは、チャネルと wait groups を使った適切な同期手法を学びます。

challenge icon

チャレンジ

簡単

goroutines を使用して複数のタスクを concurrently 実行する task runner を構築しましょう。main プログラムが継続して動作する間、タスクがバックグラウンドで実行されるシンプルなシステムを作成し、goroutines によって並行実行が可能になる仕組みを示します。

コードを2つのファイルに整理します。

  • tasks.go: タスク実行ロジックを Define します。

    Name(string)と Duration(int、milliseconds を representing)fields を持つ Task struct を作成します。

    TaskRun() method を Implement し、タスクの duration だけ sleep することで作業をシミュレートし、その後に次を Print します: Task [Name] completed

    各タスクの Run() method を goroutine として launches する RunAllTasks(tasks []Task) function を作成します。すべての goroutines を Launch した After、完了できるように 500 milliseconds sleep し、その後に次を Print します: All tasks launched

  • main.go: タスク情報を Read し、concurrent な実行を調整します。

    タスクの number を Read し、続いて各タスクの名前と duration を Read します。タスクを Create して RunAllTasks に渡します。それが戻った After、次を Print します: Main function done

次の入力が提供されます。

  • Line 1: タスクの number(integer)
  • Following lines: 各タスクについて2行 — タスク名、続いて milliseconds 単位の duration

たとえば、次の入力が与えられた場合:

3
Download
100
Process
50
Upload
75

出力には、タスクの完了(concurrency により順序は変わる場合があります)に続いて、完了メッセージが表示されます。

Task Process completed
Task Upload completed
Task Download completed
All tasks launched
Main function done

注: goroutines は concurrently 実行されるため、duration が短いタスクは通常先に完了します。タスクの完了順序は duration に依存し、短いタスクが長いタスクより先に完了します。

遅延には time.Sleeptime.Durationtime.Millisecond を使用します。RunAllTasks 内の sleep がなければ、goroutines が作業を完了する前に function が戻ることを忘れないでください。

自分で試してみよう

package main

import (
	"fmt"
)

func main() {
	// タスクの数を読み取る
	var numTasks int
	fmt.Scanln(&numTasks)

	// TODO: タスクを保持するスライスを作成する
	
	// TODO: 各タスクの名前と所要時間を読み取る
	// 各タスクについて:
	//   - タスク名を読み取る
	//   - 所要時間を読み取る(整数として)
	//   - Task を作成してスライスに追加する

	// TODO: タスクのスライスを使って RunAllTasks を呼び出す

	// TODO: Print "Main function done"
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Goオンラインコンパイラ