实际开发中,有时会遇到goroutine之间维持心跳的情况。可以利用channel来实现:
package main
import (
"log"
"time"
)
func main() {
done := make(chan struct {})
time.AfterFunc(10*time.Second, func() { close(done) })
const timeout = 2 * time.Second
pulse := heartbeat(done, timeout/2)
for {
select {
case _, ok := <-pulse:
if !ok {
return
}
log.Print("heartbeat")
case <-time.After(timeout):
return
}
}
}
func heartbeat(done <-chan struct{}, pulseInterval time.Duration) chan struct{} {
pulse := make(chan struct{})
go func() {
defer close(pulse)
beat := time.Tick(pulseInterval)
send Pulse := func() {
select {
case pulse <- struct{}{}:
default:
}
}
for {
select {
case <-done:
return
case <-beat:
sendPulse()
}
}
}()
return pulse
}
有几个点:
- 为了保障channel的producer的独占性,使用闭包
- 因其独占性,它也必须负责将channel关闭,所以用了defer
- 发送心跳的时候,为了忽略没有接收心跳的接收者的情况,所以加入了default条件。