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

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. 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
", nr)
    case <-timeout:
        fmt.Println("-----------timeout-----------
")
        //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. 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
", nr)
    case tmp2 :
        fmt.Println("-----------timeout-----------
")
        //resending
        c.send(nr)
    }
}

Your code should look like this (using select instead of 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
", nr)
    case <-timeout:
        fmt.Println("-----------timeout-----------
")
        //resending
        c.send(nr)
    }
}

Also your timeout goroutine is unnecessary. 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
", nr)
    case <-time.After(c.retransTime):
        fmt.Println("-----------timeout-----------
")
        //resending
        c.send(nr)
    }
}

This is faster, more clear and uses less memory.