Computer368520 views
中学英語812106 views
高校日本史190647 views
小学社会310694 views
いろは3014035 views
ヒストリア291495 views
高校物理160596 views
雑学1473736 views
高校生物552029 views
中学社会669043 views
Help
Tools

English

goroutine で関数を並行に実行する

Go の最大の特徴は、軽量な並行処理の仕組みである goroutine です。関数の前に go キーワードをつけるだけで、その関数を別の goroutine として並行に実行できます。

goroutine の基本

通常の関数呼び出しは、その関数が終わるまで次の行に進みません。しかし go をつけると、関数の完了を待たずにすぐ次の処理へ進みます。

package main

import (
    "fmt"
    "time"
)

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

func main() {
    go sayHello()
    fmt.Println("main continues...")
    time.Sleep(100 * time.Millisecond)
}

このコードを実行すると、main continues...Hello! が出力されます。順番は実行タイミングによって変わることがあります。

time.Sleep を入れているのは、main 関数が終了すると全ての goroutine も強制終了してしまうからです。実際のプログラムでは Sleep ではなく、WaitGroup や channel を使って goroutine の終了を待ちます。

匿名関数を goroutine で実行する

名前のない関数(匿名関数)をその場で goroutine として実行することもできます。

package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        fmt.Println("匿名関数が実行されました")
    }()

    go func(msg string) {
        fmt.Println(msg)
    }("引数も渡せます")

    time.Sleep(100 * time.Millisecond)
}

匿名関数に引数を渡す場合は、関数定義の直後に () で値を渡します。

goroutine はとても軽い

OS のスレッドは 1 つあたり数 MB のメモリを消費しますが、goroutine は数 KB 程度です。そのため、数千〜数万の goroutine を同時に動かすことも珍しくありません。

OS スレッド

メモリ消費が大きい(数 MB)。生成コストも高く、大量に作るのは難しい。

goroutine

メモリ消費が小さい(数 KB)。Go のランタイムがスケジューリングするため、大量に作っても効率的に動作する。

この軽量さが、Go で並行処理を気軽に書ける理由になっています。

注意点

goroutine を使うときに気をつけることがあります。

まず、main 関数が終わると全ての goroutine も終了します。goroutine の完了を待つ仕組みが必要です(WaitGroup や channel を使います)。

また、複数の goroutine から同じ変数を読み書きすると、データ競合が起きる可能性があります。これを防ぐには Mutex や channel を使います。

これらの対処法は別の記事で詳しく説明します。