Skip to content

Instantly share code, notes, and snippets.

@albertywu
Last active January 31, 2021 00:29
Show Gist options
  • Select an option

  • Save albertywu/2ec1f31171d11d682e4e059bc6c9c3f8 to your computer and use it in GitHub Desktop.

Select an option

Save albertywu/2ec1f31171d11d682e4e059bc6c9c3f8 to your computer and use it in GitHub Desktop.
error handling in golang
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"
)
// run quietly, unless there is an error
func main() {
wd, err := os.Getwd()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
result, err := gitVersion(wd)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Println(result)
result, err = gitLog(wd)
// example of switch type assertion to convert interface value to concrete struct implementation
// can be used to trigger certain behaviors off error subtypes
if ee, ok := err.(*ErrExecution); ok {
fmt.Fprintln(os.Stderr, "found an ErrExecution!", ee.Stderr)
os.Exit(1)
}
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
}
func gitVersion(cwd string) (string, error) {
return execute(cwd, "git", []string{"version"})
}
func gitLog(cwd string, args ...string) (string, error) {
return execute(cwd, "git", append([]string{"log"}, args...))
}
type ErrExecution struct {
error
Cmd *exec.Cmd
ExitCode int
Stderr string
}
func (e ErrExecution) Error() string {
joinedArgs := strings.Join(e.Cmd.Args, " ")
return fmt.Sprintf(`
Error: %v
Executable: %s
Command: "%s"
Stderr: %s`, e.error, e.Cmd.Path, joinedArgs, e.Stderr)
}
func execute(cwd string, command string, args []string) (string, error) {
cmd := exec.Command(command, args...)
stdout := bytes.Buffer{}
stderr := bytes.Buffer{}
cmd.Stdout = &stdout
cmd.Stderr = &stderr
cmd.Dir = cwd
err := cmd.Run()
if err != nil {
return "", &ErrExecution{error: err, Cmd: cmd, ExitCode: cmd.ProcessState.ExitCode(), Stderr: stderr.String()}
}
return stdout.String(), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment