|
That code has a race condition. One goroutine can modify an element of results at the same time a different goroutine is reading it. Running with `go run -race` detects the race. This can be fixed with a mutex. Now that we've got working code (with the mutex), we have to ask: have we proved Chris wrong? I don't think so. Chris never said it's impossible to implement this in Go. Chris just said that implementing it in Go is uglier than using an array of promises in some other language. And I think this code is uglier than an array of promises. Although I think I disagree with Chris. He says that an array of channels is significantly uglier than an array of promises. I don't think so. I think an array of channels is fine (and is easier to understand than the signal, signalCount, computed, consumed, +mutex code). package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
args := []int{5, 2, 4, 1, 8}
results := make([]chan int, len(args))
slowSquare := func(arg int, index int) {
randomMilliseconds := rand.Intn(1000)
blockDuration := time.Duration(randomMilliseconds) * time.Millisecond
<-time.After(blockDuration)
square := arg * arg
fmt.Printf("(#%d) Squared %d, index=%d, result=%2d, duration=%s, sending signal. \n", index, arg, index, square, blockDuration)
results[index] <- square
}
for i, x := range args {
results[i] = make(chan int, 1)
go slowSquare(x, i)
}
for i := 0; i < len(results); i++ {
fmt.Printf("(main) Squared %d, index=%d, result=%2d\n", args[i], i, <-results[i])
}
}
|