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の設計思想です。


コメント