普通网友 2015-09-19 12:33
浏览 34
已采纳

After time with time.After的行为不像是用代码或计时器超时

I expect the follwoing to functions to behave the same way

func fillChanTimeoutUsingTicker(maxDuration time.Duration, chanSize int) chan string {
    c := make(chan string, chanSize)
    ticker := time.NewTicker(maxDuration)
    for {
        select {
        case <-ticker.C:
            ticker.Stop()
            fmt.Println("Ticker:operation timedout")
            return c
        case c <- "Random message":
        default:
            fmt.Println("Ticker:chan is full")
            return c
        }
    }
}

func fillChanTimeoutUsingTimeAfter(maxDuration time.Duration, chanSize int) chan string {
    c := make(chan string, chanSize)
    for {
        select {
        case <-time.After(maxDuration):
            fmt.Println("time.After:operation timedout")
            return c
        case c <- "Random message":
        default:
            fmt.Println("time.After:chan is full")
            return c
        }
    }
}

calling them as :

    resWithTicker := fillChanTimeoutUsingTicker(time.Duration(1*time.Microsecond), 10000000)
    fmt.Println(len(resWithTicker))
    resWithTimeAfter := fillChanTimeoutUsingTimeAfter(time.Duration(1*time.Microsecond), 10000000)
    fmt.Println(len(resWithTimeAfter))

prints:

Ticker:operation timedout
43979
time.After:chan is full
10000000

i thought that they would behave exactly the same way and i really don't get the huge difference, any thoughts on this?

note also using a timer works as expected like in the ticker function.

  • 写回答

1条回答 默认 最新

  • doubeng1278 2015-09-19 14:11
    关注

    The problem lies within your code.

    In your first example, you are creating one ticker and use that for timing out.
    In your second example, you create a timer every time you loop:

    case <-time.After(maxDuration):
    

    As can be seen in the library sources, this is equivalent to

    case <- time.NewTimer(maxDuration).C:
    

    If you create a new Ticker/Timer every time you loop (and discard the old one), it will probably never fire.

    So, to get your second example to behave correctly, do it like this (untested):

    func fillChanTimeoutUsingTimeAfter(maxDuration time.Duration, chanSize int) chan string {
        c := make(chan string, chanSize)
        t := time.After(maxDuration)
        for {
            select {
            case <-t:
                fmt.Println("time.After:operation timedout")
                return c
            case c <- "Random message":
            default:
                fmt.Println("time.After:chan is full")
                return c
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样
  • ¥15 java的GUI的运用
  • ¥15 我想付费需要AKM公司DSP开发资料及相关开发。