見出し画像

[Go言語 入門] Channel

golangで作ってみたいものがあり、golangを学び始めたので学習したことを書いていくノート。

---------------------------------------------------

サイトマップはこちら

---------------------------------------------------

第18回 Channel


前回 Goroutin の基本を学習した。

Goroutine では return文で値を返却できないのだが、値を返却したい場合はどのようにすればいいのか。

「channel」を使おう!

以下は、Goroutineを使った配列 s の値を合計して返すプログラムである。 

// main.go

func sum(s []int, ch chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	ch <- sum
}

func main() {
	s := []int{10, 20, 30, 40, 50}
	ch := make(chan int)

	go sum(s, ch)

	x := <-ch
	fmt.Println(x)
}

// 実行結果
// 150

channel の宣言方法は以下

「変数名 := make(chan 型名)」

上記プログラムでは「ch := make(chan int)」

int型データを受信するchannel を宣言している。

処理の流れは以下

1:Goroutine の sum関数に、配列sとchannel ch を渡す。

2:変数sumに合計値を格納

3:sumの値をchannelのchへ送信

4:変数xは、受信した ch(sum)を初期値として設定

5:合計値を出力


※値を channel に渡すときは向きに注意

「channel名 <- 変数」と書くこと!

※受信した channel を変数へ格納する場合は channel 名のみでなく

「<- channel名」のように書くこと!

「<-」を忘れないように!

※channel が受信するまで次の処理が実行されない。

「sync.WaitGroup」で待つ必要がない!


~ Buffered Channels ~

channel には受信できるデータ数のキャパシティを設定することも可能。

キャパシティを設定する場合は以下のように記述する。

「変数名 := make(chan 型名 , キャパ数)

// main2.go

func main() {
	// Buffered Channels
	ch := make(chan int, 3)

	ch <- 100
	ch <- 200
	ch <- 300
	fmt.Println(<-ch)
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}
// 実行結果
// 100
// 200
// 300

以下のようにキャパシティを超えた場合はエラーとなる。

func main() {
	// Buffered Channels
	ch := make(chan int, 2) // キャパ「2」とした

	ch <- 100
	ch <- 200
	ch <- 300    // キャパオーバーでエラー
	fmt.Println(<-ch)
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

この場合は一度、受信したデータを吐き出してあげるとエラーとならずに次の channel を受信できる。

func main() {
	// Buffered Channels
	ch := make(chan int, 2)

	ch <- 100
	ch <- 200
    fmt.Println(<-ch) // 一度吐き出して空きを作る
	ch <- 300
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}
// 実行結果
// 100
// 200
// 300


~ 受信した channel をfor文を使って取り出す方法 ~

for文で取り出す場合、channel をクローズする必要がある。

※クローズしないと以下の場合、4つ目の受信データを取りに行こうとしエラーとなる。

// for文でまとめて受信する方法
ch := make(chan string, 3)

ch <- "apple"
ch <- "orange"
ch <- "peach"
close(ch)  // chクローズ

for v := range ch {
	fmt.Println(v)
}

// 実行結果
// apple
// orange
// peach

以上


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