Slide 1

Slide 1 text

The Go gopher was designed by Renée French. The gopher stickers was made by Takuya Ueda. Licensed under the Creative Commons 3.0 Attributions license. sync.Onceを完全に理解する 2022年02月25日(金) 資料:https://tenn.in/synconce

Slide 2

Slide 2 text

上田拓也 Go ビギナーズ
 Go Conference
 @tenntenn tenntenn.dev Google Developer Expert (Go) 一般社団法人 Gophers Japan 代表理事 Experts Team

Slide 3

Slide 3 text

sync.Once関数 ■ 1度しか実行しない関数 ● 1回以上Doメソッドを呼んでも意味がない ● 複数のゴールーチンから1回しか呼ばないようにするために利用する func f() { fmt.Println("Do!!") } func main() { var once sync.Once once.Do(f) once.Do(f) fmt.Println("done") } 3 2回目は実行されない Playgroundで動かす

Slide 4

Slide 4 text

sync.Once関数の使い所 ■ 必ず1度しか実行されないことが保証される ● チャネルのクローズ ○ 同じチャネルをクローズするとパニックが起きる ● 初期化 ○ 最初のメソッド実行時に1度だけ実行したい処理 ○ Google App Engineのウォームアップリクエストにおける初期化 ● 早いものがち ○ 複数のゴールーチンが実行する可能性のある処理 ○ 1度だけ、1ゴールーチンだけ実行する ○ クリティカルセクションを守る ○ 冪等性を持たせる

Slide 5

Slide 5 text

os/execパッケージでの利用例 ■ 1度しか閉じないファイル ● https://cs.opensource.google/go/go/+/master:src/os/exec/ exec.go;l=595-609 ● *os.File型を埋め込んでデコレーションしている type closeOnce struct { *os.File once sync.Once err error } func (c *closeOnce) Close() error { c.once.Do(c.close) return c.err } func (c *closeOnce) close() { c.err = c.File.Close() }

Slide 6

Slide 6 text

x/analysisパッケージでの利用例 ■ 同じ解析が2度実行されないように ● https://cs.opensource.google/go/x/tools/+/master:go/analysis/unitchec ker/unitchecker.go;l=307 参考:https://tenn.in/analysis

Slide 7

Slide 7 text

sync.Once関数の注意点 ■ パニックが起きても実行されたことになる ● やり直しは効かない ● defer文で呼び出しフラグが立てられる = パニックでもフラグが立つ ■ エラーを返すことができない ● エラーが発生しても返せない ● リトライできない

Slide 8

Slide 8 text

コードリーディングタイム https://cs.opensource.google/go/go/+/master:src/sync/once.go

Slide 9

Slide 9 text

まとめ ■ sync.Once関数は便利 ● チャネルのクローズ ● 初期化 ● 早いものがち ■ コードリーディングすると良く分かる ● パニックしたときは? ● どうやって1回に限定しているの? ● パフォーマンス改善