title: Optional timeouts in golang
body: <p>I have a function which runs a command with a timeout. It looks like this:</p>
  
  <pre><code>func run_command(cmdName string, cmdArgs []string, timeout int) (int, string) {
  
    // the command we're going to run
    cmd := exec.Command(cmdName, cmdArgs...)
  
    // assign vars for output and stderr
    var output bytes.Buffer
    var stderr bytes.Buffer
  
    // get the stdout and stderr and assign to pointers
    cmd.Stderr = &amp;stderr
    cmd.Stdout = &amp;output
  
    // Start the command
    if err := cmd.Start(); err != nil {
      log.Fatalf("Command not found: %s", cmdName)
    }
  
    timer := time.AfterFunc(time.Second*time.Duration(timeout), func() {
      err := cmd.Process.Kill()
      if err != nil {
        panic(err)
      }
    })
  
    // Here's the good stuff
    if err := cmd.Wait(); err != nil {
      if exiterr, ok := err.(*exec.ExitError); ok {
        // Command ! exit 0, capture it
        if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
          // Check it's nagios compliant
          if status.ExitStatus() == 1 || status.ExitStatus() == 2 || status.ExitStatus() == 3 {
            return status.ExitStatus(), stderr.String()
          } else {
            // If not, force an exit code 2
            return 2, stderr.String()
          }
        }
      } else {
        log.Fatalf("cmd.Wait: %v", err)
      }
      timer.Stop()
    }
    // We didn't get captured, continue!
    return 0, output.String()
  }
  </code></pre>
  
  <p>Now I want to be able to make the timeout optional. In order to fudge this a bit, I tried simply allowing timeout to be set to <code>0</code> and then having an if statement around the timer. It ended up looking like this.</p>
  
  <pre><code>if timeout &gt; 0 {
    timer := time.AfterFunc(time.Second*time.Duration(timeout), func() {
      err := cmd.Process.Kill()
      if err != nil {
        panic(err)
      }
    })
  }
  </code></pre>
  
  <p>Of course, this failed because timer is no longer defined <code>timer.Stop()</code> isn't defined now.</p>
  
  <p>So I wrapped the <code>timer.Stop()</code> with the if statement as well.</p>
  
  <pre><code>if timeout &gt; 0 {
    timer.Stop()
  }
  </code></pre>
  
  <p>This also didn't work.</p>
  
  <p>What is the correct way to do something like this? Golangs strict typing is new to me, so I'm struggling to get my head around it</p>