Hacker News new | ask | show | jobs
by patio11 3595 days ago
A corner case about Go which makes me absolutely crazy: calling Reset() on a timer which has already fired has the biggest gap between "What I expect to happen" and "What actually happens" of any stdlib I've ever worked with.

https://gist.github.com/patio11/bc883d566778c323742432c203e6...

(You can see it here in the playground, but try it on your local machine if you don't believe me and/or think the playground has an inconsistent understanding of what time actually means: https://play.golang.org/p/ltdV9dI609 )

4 comments

You never drained the longTimer channel, so when you say "We agree that longTimer has fired, right?"; that's not quite true. After you call Reset(), you're still getting the value from the first firing, because that's the first time you read from the channel at all.

The docs are quite clear on this behavior and say "Timer will send the current time on its channel after at least duration d." -- key words being at least and says nothing about when you choose to read from the channel.

It's even worse. The longTimer has fired, and it sent a message on the channel just as it was supposed to. When Reset() is called, it causes a second firing and a second message. Here is the code, corrected to illustrate. The output times are exactly as one would expect.

https://play.golang.org/p/lntgH6tkiF

This particular issue is unfortunate - it can't be changed without potentially breaking existing programs.

See https://github.com/golang/go/issues/11513 and https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVP... for some background.

Thanks for sharing! I read up on it. This whole "channel draining" concept seems powerful.
All standard libraries have their quirks, corner cases and peculiarities. This is not specific to Go. Or are you saying it is worse on Go?