简体   繁体   English

Golang为什么这个超时方案不起作用?

[英]Golang why doesn't this timeout scheme work?

So i have this code block for sending a message. 所以我有此代码块用于发送消息。 The message which gets passed to c.outChan is transmitted and if an ack is recieved in return, a "true" will be passed through the c.buffer[nr].signaler channel. 传递到c.outChan的消息将被传输,并且如果返回确认,则将通过c.buffer [nr] .signaler通道传递“ true”。 This seems to work fine, but if the message is dropped ( no ack recieved ), instead of reaching the timeout print, it just stoppes, and i don't know why. 这似乎工作正常,但如果邮件被丢弃(未收到确认),而不是到达超时打印,它只是停顿了,我不知道为什么。 Here is the code: 这是代码:

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)
    }
}

What am i doing wrong? 我究竟做错了什么?

You are using a switch for your channels, but you need a select. 您的频道使用了开关,但需要选择。 The switch doesn't know anything about channels and instead just tries to evaluate the expression in the case statements before the select. 开关对通道一无所知,只是尝试在选择之前在case语句中评估表达式。 Your current code is equivalent to this: 您当前的代码与此等效:

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)
    }
}

Your code should look like this (using select instead of switch): 您的代码应如下所示(使用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)
    }
}

Also your timeout goroutine is unnecessary. 另外,您的超时goroutine也是不必要的。 Instead of calling time.After, waiting on the channel and then sending into your own timeout channel you could directly wait on time.After. 之后,您无需等待时间,而是在通道上等待然后发送到自己的超时通道,您可以直接在时间上等待。 Example: 例:

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)
    }
}

This is faster, more clear and uses less memory. 这样更快,更清晰并且使用更少的内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM