3.7 空の構造体を使ってゴルーチン間での通知を行う

ここまで構造体の文法を紹介してきました。Go特有のTipsとして、空の構造体の利用があります。

	emptyStructType := reflect.TypeOf(&struct{}{}).Elem()
	fmt.Println(emptyStructType.Size())
	// 0

何もデータを入れることができないため、どのような用途があるのか不思議に思われる方もいるでしょう。この空の構造体には次のような用途があります。ここでは代表例として最初の項目について紹介します。

  • 並列処理のゴルーチン間での最低限の情報量のやりとり

  • mapを他の言語の集合(セット)として使う

  • 何もフィールドがないメソッド集の実装

何かの処理の終了を待って次の処理を開始するときなど、「何かが起きた」ことだけを伝えたい場合があります。このときに空の構造体のチャネルを作ります。このチャネルに空の構造体のインスタンスを与えると受信チャネルに通知が飛びます。たとえばboolを使ってもint8を使っても、最低限の1バイトは消費されてしまいますが、空の構造体であれば占有バイト数がゼロなので、消費メモリの削減になります。

	wait := make(chan struct{})
	go func() {
		// 空の構造体のインスタンスを送信
		fmt.Println("送信")
		wait <- struct{}{}
	}()
	// データサイズゼロのインスタンスを受け取る
	fmt.Println("受信待ち")
	<-wait
	fmt.Println("受信完了")

ここまで神経質にサイズ削減に取り組む必要はないと思いますが、このテクニックを利用したコードを読むこともあるかもしれないので、覚えておくと良いでしょう。 ...