見出し画像

【Go初学】Channelsは桃太郎

▼概要

Goの学習メモ。チャネルについて。

▼Channelsとは

チャネル( Channel )型は、チャネルオペレータの <- を用いて値の送受信ができる通り道です。

A Tour of Go - Channels

goroutineで非同期処理の値の受け渡しに使われるもよう。

▼Goroutineとは

goroutine (ゴルーチン)は、Goのランタイムに管理される軽量なスレッドです。

A Tour of Go - Goroutines

並行して処理を行う機構。

▼チャネルの概念の理解

Goの学習を進めていて最初に戸惑ったのがチャネルの存在。
恐らくC言語のポインタ仕様並に、初学者が最初に躓くポイントなんだろうと思う。
Microsoft学習カリキュラムの「MicroSoft Learn」でGoのカリキュラムがあるが、そちらでも「これまでに学んだことを忘れる必要があるかも」と言っているほど。

コンカレンシーは、独立した複数のアクティビティの構成です。たとえば、Web サーバーにより、複数のユーザー要求が同時に、さらに自律的に処理されるときに実行される作業などです。
Go のコンカレンシーのしくみについて学習を始める前に、他のプログラミング言語からこれまでに学んだことを忘れる必要があるかもしれません。 Go のアプローチは大きく異なります。

Microsoft Learn - Go のコンカレンシーのしくみについて学ぶ

別の言語で触れたことがあるReactive系ライブラリの「Observableオブジェクトを使ったイベントストリームのようなもの」か?と捉えると、何をする目的のものなのかイメージが掴みやすかった。

イベントストリームの概念は、自分は桃太郎の桃が流れてくるのを待つシーンがそれにあたるかなと理解している。

- お婆さんが桃を待つだけの状態

  • 川:イベントストリーム = channel

  • お婆さん:イベント購読者 = main goroutine

  • 神:イベント発行者(桃を流す側) = 別goroutine

登場人物がお婆さんだけの状態だとどうなるか。お婆さんは桃(イベント)が流れてくることを期待している。

package main

func main() {
	// 桃を流したら連絡してもらう手段を作成(イベントが発行されるストリーム)
	momoChannel := make(chan bool)

	// 桃が流れるのを待つ
	<-momoChannel
}

連絡してもらう手段として糸電話(チャネル)を作成した。しかし誰にも糸電話を渡していないため、お婆さんは永遠に桃が流れるのを待ち続け、不謹慎なdeadlockとなる。

$ go run main.go
$ fatal error: all goroutines are asleep - deadlock!

- 神(イベント発行者)と約束

package main

import (
	"fmt"
	"time"
)

func main() {
	// 桃を流したら連絡してもらう(イベントが発行されるストリーム)
	momoChannel := make(chan bool)

	// 神の御業
	go func(channel chan bool) {
		fmt.Println("桃を流す準備を開始")

		// ちょっと時間が掛かった想定
		time.Sleep(3 * time.Second)

		// 流したことを連絡
		fmt.Println("桃を流しました")
		channel <- true
	}(momoChannel)

	// 桃が流れるのを待つ
	<-momoChannel

	fmt.Println("桃を手に入れました")
}
$ go run main.go
$ 桃を流す準備を開始
$ 桃を流しました
$ 桃を手に入れました

神(匿名関数のgoroutine)に連絡手段の糸電話(チャネル)を渡し、桃を流したら連絡する約束をした。神が桃を流したことを連絡したため、永遠に待ち続けることなくお婆さんは桃を手に入れることができた。

問題があるケースとして、糸電話なのでお婆さんが洗濯に行ったりして糸電話から離れる(チャネルを受信しない)と、神がお婆さんと連絡が取れなくなりお婆さん戻り待ちとなり、神の仕事がストップする。
またお婆さんが糸電話を渡しておいてすぐ「やっぱ桃いいわ」と糸電話を捨てる(close())と、神が連絡を取ろうとした時に文字通りパニック(panic())してエラーとなる。

あとがき

永遠に待ち続けたりパニックして世界がエラーとなったりGoの糸電話は怖い印象。また上記はバッファ無しのチャネルのケース。バッファ有りの場合は「X個までしか同時に桃を流せない川」というイメージだろうか。


この記事が気に入ったらサポートをしてみませんか?