rampatowl
rampatowl

Reputation: 1772

How to check for type errors in errors.Errorf()?

Calls to string formatting functions like fmt.Printf seem to be a weak spot for the Go compiler. I end up with lots of bugs (using the wrong formatter after a refactor, forgetting to include all the arguments) that only reveal themselves at runtime. So I end up having to squint hard every time I write one of these.

I did some research today and discovered go tool vet, which appears to work for fmt.Printf, but it doesn't catch mistakes in errors.Errorf (see below).

import "github.com/pkg/errors"

func ReturnError(s string, i int) error {
    // Swap %d and %s, and forget to include the second argument
    return errors.Errorf("invalid arguments %d and %s", s)
}

Is there an analog to go tool vet that can capture string formatting errors in errors.Errorf()? Also, for my own understanding, why is this such a hard problem? It doesn't seem any more difficult for the Go compiler to catch string formatting type errors than any other kind of type errors.

Upvotes: 0

Views: 5343

Answers (1)

robx
robx

Reputation: 2329

You can tell go vet which functions to check for (compare godoc.org/cmd/vet):

$ cat x.go
package main

import "github.com/pkg/errors"

func ReturnError(s string, i int) error {
    // Swap %d and %s, and forget to include the second argument
    return errors.Errorf("invalid arguments %d and %s", s)
}
$ go vet x.go 
$ go vet -printfuncs Errorf x.go 
# command-line-arguments
./x.go:7: Errorf format %d has arg s of wrong type string

It's not straightforward to do this better for a number of reasons:

  • Format strings are run-time values: You might well call fmt.Sprintf(prefix + "%s", ...). So it is impossible to catch all invalid format strings at compile time.
  • Format strings don't have a special type. Hence the compiler can't easily determine that some function (errors.Errorf in this case) expects its arguments to behave like fmt.Printf just by looking at the function definition.

Upvotes: 4

Related Questions