package main
import (
"fmt"
"sync"
)
func main() {
ch1 := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(<-ch1)
}()
ch1 <- 10
close(ch1)
v, ok := <-ch1
fmt.Printf("%v %v\n", v, ok)
wg.Wait()
ch2 := make(chan int, 2)
ch2 <- 1
ch2 <- 2
close(ch2)
v, ok = <-ch2
fmt.Printf("%v %v\n", v, ok)
v, ok = <-ch2
fmt.Printf("%v %v\n", v, ok)
v, ok = <-ch2
fmt.Printf("%v %v\n", v, ok)
}
このコードは、goroutineを使って非同期にデータを受信し、channelを使ってデータの送受信を行う基本的な例です。
gooroutineは、Go言語の並行処理を実現するための仕組みです。goキーワードを使って新しいgoroutineを作成します。goroutineは軽量なスレッドとして動作し、独立して実行されます。
channelは、goroutine間でデータを安全にやり取りするための構造です。Goでは、channelを使って値を送受信することができます。
ch1 := make(chan int)
-
channelの作成: 整数型のchannel
ch1
を作成します。このchannelは、goroutine間で整数を送受信するために使用されます。
var wg sync.WaitGroup
-
WaitGroupの宣言:
sync.WaitGroup
型の変数wg
を宣言します。これにより、複数のgoroutineが終了するのを待つことができます。
wg.Add(1)
-
カウントの追加:
wg
に1を追加します。これにより、現在1つのgoroutineが終了するのを待つことを示します。
go func() {
- goroutineの開始: 無名関数を新しいgoroutineとして実行します。この関数内のコードは、メインのgoroutineとは別に並行して実行されます。
defer wg.Done()
-
defer文: この行は、関数の終了時に
wg.Done()
を呼び出すことを指定します。これにより、wg
のカウントが1減ります。goroutineが終了したことを示します。
fmt.Println(<-ch1)
-
channelからの受信:
ch1
から値を受信し、その値をコンソールに出力します。<-ch1
は、ch1
から値を読み取る操作です。この操作は、ch1
に値が送信されるまでブロックされます。
}()
- 無名関数の終了: ここで無名関数の定義が終了し、goroutineが実行を開始します。
ch1 <- 10
-
channelへの送信: メインのgoroutineから
ch1
に整数10を送信します。この操作により、先ほどのgoroutineがfmt.Println
で受信した値として10が出力されます。
close(ch1)
-
channelの閉鎖:
ch1
を閉じます。これにより、これ以上の値を送信しないことを示します。受信側は、channelが閉じられたことを知ることができます。
v, ok := <-ch1
-
channelからの再受信:
ch1
から値を受信しようとしますが、ch1
は既に閉じられているため、ok
はfalse
になります。v
には0が設定されます(整数型のデフォルト値)。
fmt.Printf("%v %v\n", v, ok)
-
出力: 受信した値
v
と、受信が成功したかどうかを示すok
の値をフォーマットしてコンソールに出力します。
wg.Wait()
-
WaitGroupの待機:
wg
のカウントが0になるまでメインのgoroutineをブロックします。ここでは、先ほどのgoroutineが終了するのを待ちます。
ch2 := make(chan int, 2)
-
バッファ付きchannelの作成: 整数型のバッファ付きchannel
ch2
を作成します。このchannelは最大2つの値を保持できます。
ch2 <- 1
-
channelへの送信:
ch2
に整数1を送信します。この操作は非ブロッキングです。バッファが空いているため、すぐに送信が完了します。
ch2 <- 2
-
channelへの送信:
ch2
に整数2を送信します。この操作も非ブロッキングで、バッファが空いているため、すぐに完了します。
close(ch2)
-
channelの閉鎖:
ch2
を閉じます。これにより、これ以上の値を送信しないことを示します。
v, ok = <-ch2
-
channelからの受信:
ch2
から値を受信します。ここでは、最初に送信された値1が受信され、v
に1が、ok
にtrue
が設定されます。
fmt.Printf("%v %v\n", v, ok)
-
出力: 受信した値
v
と、受信が成功したかどうかを示すok
の値をフォーマットしてコンソールに出力します。
v, ok = <-ch2
-
channelからの再受信:
ch2
から次の値を受信します。ここでは、2が受信され、v
に2が、ok
にtrue
が設定されます。
fmt.Printf("%v %v\n", v, ok)
-
出力: 受信した値
v
と、受信が成功したかどうかを示すok
の値をフォーマットしてコンソールに出力します。
v, ok = <-ch2
-
channelからの再受信:
ch2
から値を受信しようとしますが、ch2
は既に閉じられているため、v
には0が、ok
にはfalse
が設定されます。
fmt.Printf("%v %v\n", v, ok)
-
出力: 受信した値
v
と、受信が成功したかどうかを示すok
の値をフォーマットしてコンソールに出力します。