import "once"

このパッケージで唯一提供されているDo関数は、指定した関数を必ず一度だけ実行します。通常、初期化処理として使用します。

パッケージファイル

once.go

Do関数

func Do(f func())

このDo関数だけが唯一、このパッケージ内でエキスポートされています。一度だけ実行する初期化処理(init関数では呼び出さない)を引数を持たない関数f()に記述しておき、それをパラメータとしてDo関数を呼び出します。

Do(f)

複数のプロセスから同一のfパラメータを使って同時にDo(f)を呼び出したときも、f関数は一度だけ呼び出されます。
f関数から復帰するまでは、他のDo関数の呼び出しはブロックされます。

ただし、通常func()式は評価されるたびに異なる値が返されるため、func()式をDo関数に渡すのは誤った使い方です。
下はその例です。

func f(x int) {
	Do(func() { fmt.Println(x) })
}

これは、下と同じことです。

func f(x int) {
	fmt.Println(x)
}

最初のコードではf関数が実行される都度、func()式によって新しい関数が作られます。そのため作成された関数すべてが一回ずつ動作してしまいます。