我正在尝试对我的程序进行测试,该程序将在设定的时间间隔内保存到磁盘。我的问题是我加了时间。无论测试时间长短,程序都将挂起。
我的预期行为是我允许它进入睡眠状态,并且go例程应该在后台运行,并保存到磁盘上。
这是正在测试中作为goroutine运行的功能。
nodeservice.go
func runRegistryBackup(reg *NodeRegistry, interval int, killchan chan bool) {
log.SetPrefix("[Registry Backup]\t")
log.Printf("Intializing backup every %d seconds", interval)
select {
case <-time.Tick(time.Duration(interval) * time.Second):
log.Println("Backing up node registry to disk")
reg.write()
case <-killchan:
log.Println("Flushing data to disk")
reg.write()
defer func() { killchan <- true }()
//defer close(killchan)
return
}
}
这是测试。我评论了添加该行将冻结该程序的行
nodeservice_test.go
func TestRunRegistry(t *testing.T) {
// need registry, interval, bool chan
// setup
fi, _ := ioutil.TempFile("", "msg-serv-test-")
defer os.Remove(fi.Name())
reg := MakeNodeRegistry(fi.Name())
name := "test"
ip := "10.0.0.1"
port := "0"
tls := false
node1 := MakeNode(name, ip, port, tls)
reg.addNode(node1)
interval := 5
kill := make(chan bool)
// test the interval
go runRegistryBackup(reg, interval, kill)
// let run for a little
time.Sleep(time.Minute) // adding this line hangs the whole program
// test kill
kill <- true
<-kill
actReg := BuildRegistry(fi.Name())
for key, eval := range reg.Nodes {
val := actReg.Nodes[key]
if eval != nil && val != nil {
assert(t, *val, *eval)
} else {
t.Logf("Expected Hash: %d \t Expected Node: %v", key, eval)
t.Logf("Key %d not found for Node %v", key, val)
t.Fail()
}
}
}
以下是日志的输出,显示该间隔仅运行一次然后挂起。
[Registry Backup] 2019/07/19 13:29:51 Intializing backup every 5 seconds
[Registry Backup] 2019/07/19 13:29:56 Backing up node registry to disk
对于引起此问题的原因的任何见解,将不胜感激。
答案 0 :(得分:1)
函数runRegistryBackup
调用write()
一次,然后退出。然后,主goroutine阻止发送到kill
。
通过在函数中添加循环来修复。在循环之前创建一次股票行情记录,并在返回时停止股票行情记录。
func runRegistryBackup(reg *NodeRegistry, interval int, killchan chan bool) {
log.SetPrefix("[Registry Backup]\t")
log.Printf("Intializing backup every %d seconds", interval)
t := time.NewTicker(time.Duration(interval) * time.Second)
defer t.Stop()
for {
select {
case <-t.C:
log.Println("Backing up node registry to disk")
reg.write()
case <-killchan:
log.Println("Flushing data to disk")
reg.write()
defer func() { killchan <- true }()
return
}
}
}
无缓冲的kill
通道为程序增加了一些脆弱性。例如,如果将runRegistryBackup
修改为在发生写错误时退出,并且main尝试在该错误之后终止备份,则main将永远阻塞。通过缓冲通道来解决。
kill := make(chan bool, 1)
答案 1 :(得分:0)
go runRegistryBackup(reg, interval, kill)
返回case <-time.Tick
,无法从终止通道读取任何内容,因此主例程在kill <- true
上阻塞。
我不完全了解您的程序的逻辑,因此让事情正常工作的最简单方法是使kill
通道缓冲
kill := make(chan bool, 1)