2022/06/12

[golang] chan で待つ (3)

2番目の記事で疑問になっていたところを解消しておこう。

hiro99ma blog: [golang] chan で待つ (2)
https://blog.hirokuma.work/2022/06/golang-chan-2.html

のこちら。

その後で A が終わって待ち解除になると B 待ち状態になるが、既に処理が終わった B についてどうなるのかわからん。

についてだ。


まず、勘違いしていた件。

 

done := make(chan struct{}, 3)

こう書いたとしても、

done[0] <- struct{}{}

のようには書けないということだ。
make() は capacity を設定するものだから len() ではなく cap() を使って容量を取ってくるのだった。

 

それを踏まえて。

package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Printf("start\n")
	done := []chan struct{}{
		make(chan struct{}),
		make(chan struct{}),
		make(chan struct{}),
	}
	go func() {
		fmt.Printf("goroutine start - 1\n")
		time.Sleep(10 * time.Second)
		fmt.Printf("goroutine done - 1\n")
		done[0] <- struct{}{}
		fmt.Printf("goroutine sent - 1\n")
	}()
	go func() {
		fmt.Printf("goroutine start - 2\n")
		time.Sleep(5 * time.Second)
		fmt.Printf("goroutine done - 2\n")
		done[1] <- struct{}{}
		fmt.Printf("goroutine sent - 2\n")
	}()
	go func() {
		fmt.Printf("goroutine start - 3\n")
		time.Sleep(3 * time.Second)
		fmt.Printf("goroutine done - 3\n")
		done[2] <- struct{}{}
		fmt.Printf("goroutine sent - 3\n")
	}()
	fmt.Printf("waiting...\n")
	<-done[0]
	fmt.Printf("done - 1\n")
	<-done[1]
	fmt.Printf("done - 2\n")
	<-done[2]
	fmt.Printf("done - 3\n")
	fmt.Printf("all done\n")
}

実行。

$ go run .
start
waiting...
goroutine start - 3
goroutine start - 1
goroutine start - 2
goroutine done - 3
goroutine done - 2
goroutine done - 1
goroutine sent - 1
done - 1
done - 2
done - 3
goroutine sent - 3
all done

時間の経過が見えないが、「goroutine done - 1」以降は一気に出力されている。
「sent」のログは全部出ていないが、これはその前にプロセスが終了したからだろう。

まあ、これなら前回の最後に書いた for でぐるぐる回して待つ方がシンプルに見えるな。