how to implement a go timeout
tags: learning go programming
content
-
see here:
go-select-timeout#go-select-timeout
-
in this example, we are using
selectto listen to timeouttime.After- go
selectis a communication mechanism, see go-select-and-switch selectis listening on channels
- go
-
to implement a
time.Aftertimeout function, we need the function to return a channel- it should take in a
time.Duration - hence the signature:
- it should take in a
func myTimeout (d time.Duration) chan bool- the channel could be any type, i think?
- with the signature, we can potentially have:
func myTimeout (d time.Duration) chan bool {
c := make(chan bool)
time.Sleep(d)
c <- true
ruturn c
}- and use it like:
for {
select {
case <- someChannel:
// ...do something
case <- myTimeout(1 * time.Second):
// ...do something else
}
}-
but if we run this it’s gonna cause a deadlock!
-
deadlock means that something is blocked!
- in this case, it’s the caller function that’s being blocked
- because when the caller calls
myTimeoutmyTimeoutproceeds to sleep- the caller can’t do anything before the duration passes
- which means the caller is blocked
- but the whole point of timeout is that:
- timeout doesn’t block the main thread
- main thread is listening on a channel
- timeout finishes and write to the channel
- in this case:
- when
myTimeoutreturns the channel
- when
-
the correct implementation is:
myTimeoutcreates a channel and return the channel immediately, so the caller doesn’t get blocked- the caller now have a channel to listen to (a channel to be written into by
myTimeout) myTimeoutwrites to the channel afterduration
-
key:
myTimeouthas to- return immediately
- still writes back to the channel
-
hence there should be a go routine in
myTimeout
func myTimeout (d time.Duration) chan bool {
c := make(chan bool)
go func() {
time.Sleep(d)
c <- true
}()
return c
}