1. send a close message on the channel that stops the goroutine
2. use a Context instance - `ctx.Done()` returns a channel you can select on
Both are quite easy to grasp and implement.
1. send a close message on the channel that stops the goroutine
2. use a Context instance - `ctx.Done()` returns a channel you can select on
Both are quite easy to grasp and implement.
Since CSP is mentioned, how much would this apply to most applications anyway? If I write a small server program, I probably won't want to write it on paper first. With one possible exception I never heard of anyone writing programs based on CSP (calculations?)
CSP is really in the realm of formal methods. No you wouldn't formulate your server program as CSP, but if you were writing software for a medical device, perhaps.
This is the FDR4 model checker for CSP, it's a functional programming language that implements CSP semantics and may be used to assert (by exhaustion, IIRC) the correctness of your CSP model.
I believe I'm in the minority of Go developers that have studied CSP, I fell into Go by accident and only took a CSP course at university because it was interesting, however I do give credit to studying CSP for my successes with Go.
Assuming the number of players are set up front, and players can only play or leave, not join. If the expectation is that players can come and go freely and the game ends some time after all players have left, I believe this pattern can still be used with minor adjustment
(please overlook the pseudo code adjustments, I'm writing on my phone - I believe this translates reasonably into compilable Go code):
type Message struct {
exit bool
score int
reply chan bool
}
type Game struct {
bestScore int
players int // > 0
messages chan Message
}
func (g *Game) run() {
for message := range g.messages {
if message.exit {
g.players = g.players - 1;
if g.players == 0 {
return
}
continue
}
if g.bestScore < 100 && g.bestScore < message.score {
g.bestScore = message.score
}
acceptingScores := g.bestScore < 100
message.reply <- acceptingScores
}
}
func (g *Game) HandlePlayer(p Player) error {
for {
score, err := p.NextScore()
if err != nil {
g.messages <- { exit: true
}
return err
}
g.messages <- { score, reply }
if not <- reply {
g.messages <- { exit: true }
return nil
}
}
}