Skip to content

Instantly share code, notes, and snippets.

@arnehormann
Created November 15, 2013 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnehormann/7484752 to your computer and use it in GitHub Desktop.
Save arnehormann/7484752 to your computer and use it in GitHub Desktop.
reduce noise in example programs
type closer interface {
Close() error
}
type errorMessage string
func (err errorMessage) Error() string {
return string(err)
}
const (
ErrNotCloser errorMessage = "expected a Closer"
)
func HandleError(errHandler func(err interface{})) func() {
return func() {
if err := recover(); err != nil {
errHandler(err)
}
}
}
func PrintError(errHandler func(err ...interface{})) func() {
return func() {
if err := recover(); err != nil {
errHandler(err)
}
}
}
func CheckError(err error) {
if err != nil {
panic(err)
}
}
func CallClose(closeable interface{}, err error) func() error {
CheckError(err)
c, ok := closeable.(closer)
if !ok {
panic(ErrNotCloser)
}
return c.Close
}
func CallCloseChecked(closeable interface{}, err error) func() error {
Close := CallClose(closeable, err)
return func() error {
CheckError(Close())
return nil
}
}
@arnehormann
Copy link
Author

An example:

The function TestSelectBlob from this test

func TestSelectBlob(t *testing.T) {
    db, err := sql.Open("mysql", "tcp(localhost:3306)/")
    if err != nil {
        t.Fatal(err)
    }
    defer db.Close()
    value := []byte{0x64, 0x00, 0x01, 0x01, 0x00, 0x12, 0x21, 0x00, 0x00, 0x00}
    rows, err := db.Query(`SELECT ?`, value)
    if err != nil {
        t.Fatal(err)
    }
    defer rows.Close()
    if !rows.Next() {
        panic("no rows returned")
    }
    var tmp interface{}
    err = rows.Scan(&tmp)
    if err != nil {
        t.Fatal(err)
    }
    if got, ok := tmp.([]byte); ok && bytes.Equal(value, got) {
        fmt.Println("got the value back")
    } else {
        fmt.Printf(
            "there's trouble (received type is %T):\n\tgot  %q\n\twant %q\n",
            tmp, tmp, value,
        )
    }
}

...looks like this with errcheck:

func TestSelectBlob(t *testing.T) {
    defer PrintError(t.Fatal)()
    db, err := sql.Open("mysql", "tcp(localhost:3306)/")
    defer CallCloseChecked(db, err)
    value := []byte{0x64, 0x00, 0x01, 0x01, 0x00, 0x12, 0x21, 0x00, 0x00, 0x00}
    rows, err := db.Query(`SELECT ?`, value)
    defer CallCloseChecked(rows, err)
    if !rows.Next() {
        panic("no rows returned")
    }
    var tmp interface{}
    CheckError(rows.Scan(&tmp))
    if got, ok := tmp.([]byte); ok && bytes.Equal(value, got) {
        fmt.Println("got the value back")
    } else {
        fmt.Printf(
            "there's trouble (received type is %T):\n\tgot  %q\n\twant %q\n",
            tmp, tmp, value,
        )
    }
}

... but errcheck also tests for errors on Close!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment