title: チャネル
date: 2022-06-29 14:39:00
toc: false
index_img: http://api.btstu.cn/sjbz/?lx=m_dongman&cid=7
category:
- Go
tags: - 解決
- 回数
- ポインター
注意:共有メモリを通信して共有しないでください。
- すべてのチャネルの送信操作はブロックされます(ブロックとも呼ばれます)。
- waitGroup を使用する場合は、必ずポインターと組み合わせて使用してください。
- 実際の問題を解決するには、順序が保証されているかどうか、または順不同の状況で検査する必要があります。
コードを直接示します。コメントに注意してください:
package main
import "fmt"
type worker struct {
in chan int
done chan bool
}
func main() {
const count = 4
var workers [count]worker
for i := 0; i < count; i++ {
workers[i] = createWorker(i)
}
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
for _, worker := range workers {
<-worker.done
<-worker.done
}
}
func doWork(id int, w worker) {
for {
fmt.Printf("No.%d worker received: %c\n", id, <-w.in)
go func() { w.done <- true }() // バッファ付きチャネルを作成して問題を解決することもできます。ここでは done: make(chan bool, 1) と同じ効果で、ブロックされなくなり、結果が順不同になります。
// w.done <- true
}
}
func createWorker(id int) worker {
w := worker{
in: make(chan int), // inチャネルを追加すると、2回のデータ送信が完了し、2回のdoneの受信が開始され、結果が順不同になります。
done: make(chan bool), // doneチャネルを追加すると、最初のデータ送信が完了すると、直ちに2回目のデータ送信が開始され、結果が順不同になります。
}
go doWork(id, w)
return w
}
sync.WaitGroup
を使用して実装する場合:
package main
import (
"fmt"
"sync"
)
type worker struct {
in chan int
done *sync.WaitGroup
}
func main() {
const count = 4
var wg sync.WaitGroup
var workers [count]worker
for i := 0; i < count; i++ {
workers[i] = createWorker(i, &wg)
}
wg.Add(count * 2)
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
wg.Wait()
}
func doWork(id int, w worker) {
for {
fmt.Printf("No.%d worker received: %c\n", id, <-w.in)
w.done.Done()
}
}
func createWorker(id int, wg *sync.WaitGroup) worker {
w := worker{
in: make(chan int),
done: wg,
}
go doWork(id, w)
return w
}
関数とWaitGroup
を一緒に使用する:
package main
import (
"fmt"
"sync"
)
type worker struct {
in chan int
done func()
}
func main() {
const count = 4
var wg sync.WaitGroup
var workers [count]worker
for i := 0; i < count; i++ {
workers[i] = createWorker(i, &wg)
}
wg.Add(count * 2)
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
wg.Wait()
}
func doWork(id int, w worker) {
for {
fmt.Printf("No.%d worker received: %c\n", id, <-w.in)
w.done()
}
}
func createWorker(id int, wg *sync.WaitGroup) worker {
w := worker{
in: make(chan int),
done: wg.Done,
}
go doWork(id, w)
return w
}