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 select to listen to timeout time.After

  • to implement a time.After timeout function, we need the function to return a channel

    • it should take in a time.Duration
    • hence the signature:
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 myTimeout
      • myTimeout proceeds 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 myTimeout returns the channel
  • the correct implementation is:

    • myTimeout creates 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)
    • myTimeout writes to the channel after duration
  • key: myTimeout has to

    1. return immediately
    2. 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
}

up

down

reference