所以我有这个代码块用于发送消息。传递给c.outChan的消息被传输,如果收到ack,则“true”将通过c.buffer [nr] .signaler通道传递。这似乎工作正常,但如果消息被删除(没有收到ack),而不是达到超时打印,它只是停止,我不知道为什么。这是代码:
func (c *uConnection) send(nr uint32) {
//transmitt message
c.outChan <- c.buffer[nr].msg
timeout := make(chan bool, 1)
go func() {
timeoutTimer := time.After(c.retransTime)
<-timeoutTimer
timeout <- true
}()
switch {
case <-c.buffer[nr].signaler:
fmt.Printf("Ack confirmed: %v\n", nr)
case <-timeout:
fmt.Println("-----------timeout-----------\n")
//resending
c.send(nr)
}
}
我做错了什么?
答案 0 :(得分:4)
您正在为频道使用开关,但需要选择。交换机对通道一无所知,只是尝试在select语句之前评估case语句中的表达式。您当前的代码与此相同:
func (c *uConnection) send(nr uint32) {
//transmitt message
c.outChan <- c.buffer[nr].msg
timeout := make(chan bool, 1)
go func() {
timeoutTimer := time.After(c.retransTime)
<-timeoutTimer
timeout <- true
}()
tmp1 := <-c.buffer[nr].signaler // this will block
tmp2 := <-timeout
switch {
case tmp1 :
fmt.Printf("Ack confirmed: %v\n", nr)
case tmp2 :
fmt.Println("-----------timeout-----------\n")
//resending
c.send(nr)
}
}
您的代码应该如下所示(使用select而不是switch):
func (c *uConnection) send(nr uint32) {
//transmitt message
c.outChan <- c.buffer[nr].msg
timeout := make(chan bool, 1)
go func() {
timeoutTimer := time.After(c.retransTime)
<-timeoutTimer
timeout <- true
}()
select {
case <-c.buffer[nr].signaler:
fmt.Printf("Ack confirmed: %v\n", nr)
case <-timeout:
fmt.Println("-----------timeout-----------\n")
//resending
c.send(nr)
}
}
此外,您的超时goroutine也是不必要的。而不是调用time.After,等待频道,然后发送到你自己的超时频道,你可以直接等待准时。后。例如:
func (c *uConnection) send(nr uint32) {
//transmitt message
c.outChan <- c.buffer[nr].msg
select {
case <-c.buffer[nr].signaler:
fmt.Printf("Ack confirmed: %v\n", nr)
case <-time.After(c.retransTime):
fmt.Println("-----------timeout-----------\n")
//resending
c.send(nr)
}
}
这更快,更清晰,使用更少的内存。