体はドクペで出来ている

インフラ、Goの割合が多い技術ブログ

書籍勉強記を始めます & Golangの sync.Once についてメモ

始めに

オライリーGo言語によるWebアプリケーション開発 を購入したので今日から少しずつ進め、そのレポートを連載したいと思います。

始めは1章ごとにメモや感想を書いて行こうかと思ったのですが、やってみたらそこそこのボリュームになりそうだったので進めながら随時小ネタとしてメモを書いて行くことにしました。割と基本的なこと(package紹介とか)や既出なことでも定着強化とこれからGolangを学ぶ人に向けて敢えて細かい粒度で書いて行こうと思います。

というわけで今日は第1章に登場する sync.Once 型について。

追記> (手違いで古い下書きを投稿してしまった)

第1章について

この章ではWebSocketを使ったチャットアプリケーションを実装します。これは複数のユーザーが同時に接続し発言はリアルタイムに全員へ共有されます。

このアプリケーションの中ではHTMLテンプレートをコンパイルするのですが、これは何度も行う必要はないため sync.Once 型を使って複数のgoroutineが動作しても一度だけのコンパイルを行われ無駄が発生しないような動作とします。

追記ここまで>

sync.Once 型

Golangには並行処理に関する強力な機能があります。これらは sync パッケージにまとめられており非同期処理や排他制御等を行いたい時はよくお世話になることでしょう。

sync.Once 型には Do というメソッドがありこれに func を渡すことで実行することができますが、名前の通り一度しか実行されません(2回以上 Do メソッドを呼んでも何も起こらない)。

検証コード

func main() {
    var once1 sync.Once
    once1.Do(ikkaime) // 1回目なので呼び出される
    once1.Do(nikaime) // 2回目なので呼び出されない

    var once2 sync.Once
    once2.Do(ikkaime) // 新しく生成された後の1回目なので呼び出される
    once2.Do(nikaime) // 2回目なので呼び出されない
}

func ikkaime() {
    fmt.Println("1回目だけ!")
}

func nikaime() {
    fmt.Println("2回目は実行されない!")
}

結果

実際にGo Playgroundで実行してみて下さい。

sync.Once 型の once1once2 でそれぞれ1回目には ikkaime() 、2回目には nikaime() という関数を2回ずつ呼び出していますが、どちらも1回目しか実行されていないことがわかるかと思います。

何らかの一度しか実行したくない性質のもの(初期化処理等)で有用です。