実務向け】Go channelの使い方|並行処理の基本から応用まで

プログラム

Go言語の強みといえば「並行処理」。
その中心となるのが**channel(チャネル)**です。

goroutineと組み合わせることで、安全かつ効率的な並行処理を実現できます。

本記事では、Goのchannelについて「使い方・並行処理・実務での応用」を解説します。


channelとは?

channelは、goroutine間でデータを受け渡すための仕組みです。

ch := make(chan int)

👉 イメージ

  • goroutine同士の「通信パイプ」

基本の使い方(送受信)

ch := make(chan string)

// 送信
ch <- "Hello"

// 受信
msg := <-ch

👉

  • ch <- 値 → 送信
  • <-ch → 受信

goroutineと組み合わせる

package main

import "fmt"

func main() {
ch := make(chan string)

go func() {
ch <- "Hello Channel"
}()

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

👉 goroutine間で安全にデータ共有


ブロッキング動作(重要)

channelはデフォルトで👇

  • 送信 → 受信されるまで待つ
  • 受信 → データが来るまで待つ

👉 同期処理として動く


バッファ付きchannel

ch := make(chan int, 2)

ch <- 1
ch <- 2

👉 特徴

  • 指定数までブロックしない
  • パフォーマンス向上

実務での使い方①:並列処理

func worker(ch chan int) {
ch <- 1
}

func main() {
ch := make(chan int)

for i := 0; i < 5; i++ {
go worker(ch)
}

for i := 0; i < 5; i++ {
fmt.Println(<-ch)
}
}

👉 並列処理の基本パターン


実務での使い方②:処理完了の通知

done := make(chan bool)

go func() {
// 処理
done <- true
}()

<-done

👉 処理完了の待機に使う


実務での使い方③:selectで制御

select {
case msg := <-ch1:
fmt.Println(msg)
case msg := <-ch2:
fmt.Println(msg)
}

👉 複数channelを扱える


応用:タイムアウト処理

select {
case res := <-ch:
fmt.Println(res)
case <-time.After(2 * time.Second):
fmt.Println("タイムアウト")
}

👉 API開発でよく使う


よくあるミス

❌ channel閉じ忘れ

close(ch)

👉 終了処理は明示する


❌ デッドロック

ch := make(chan int)
ch <- 1 // 受信がない

👉 プログラム停止する


ベストプラクティス

  • goroutineとセットで使う
  • closeで終了管理
  • selectで制御
  • バッファは必要なときだけ

まとめ

Go channelのポイント👇

  • goroutine間の通信手段
  • 並行処理の中核
  • ブロッキング動作を理解する
  • selectで制御する

💡 結論

👉
「共有メモリではなく、通信で並行処理する」

これがGoの設計思想です。

コメント

タイトルとURLをコピーしました