0

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.

1 Answer 1

4

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.
Sign up to request clarification or add additional context in comments.

3 Comments

Ah, -printfuncs is just what I was looking for. One clarification: what do you mean by "format strings are run-time values"? It seems that they can be analyzed at compile-time like anything else (since the types of the arguments are known).
I tried to clarify the part about why this is difficult, does it make sense now?
Ah okay, you’re saying that the first art of Printf can be a variable whose value isn’t known at compile time. It does seem like in most uses the first arg is a constant string, but I guess Go doesn’t want to disambiguate these cases?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.