code: func doAsyncTimeout(f func() error, tmFunc func(error), timeout time.Duration) error {
  	errs := make(chan error)
  	go func() {
  		err := f()
  		select {
  		case errs <- err:
  		default:
  			if tmFunc != nil {
  				tmFunc(err)
  			}
  		}
  	}()
  	select {
  	case err := <-errs:
  		return err
  	case <-time.After(timeout):
  		return errors.New("operation timeout")
  	}
  }
docs: // doAsyncTimeout runs f in a different goroutine
  //	if f returns before timeout elapses, doAsyncTimeout returns the result of f().
  //	otherwise it returns "operation timeout" error, and calls tmFunc after f returns.