-
-
Notifications
You must be signed in to change notification settings - Fork 377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggest errors.New over fmt.Errorf with single string parameter and no formatting #1550
Comments
I assumed revive or another golangci-lint linter would detect it but it doesn't. While it does detect fmt.Sprintf("whatever") is detected by gosimple S1039 |
My concern with this check would be consistency with surrounding code. Should |
please note fmt.Errorf("whatever", "whatever") printf: fmt.Errorf call has arguments but no formatting directives (govet) |
I would recommend using https://github.com/golang/go/blob/fa08befb25e6f4993021429aa222dad71a27ed07/src/fmt/errors.go#L8 Side remark, maybe some linter would recommend using a sentinel error at some point when using |
To put a number on that:
I get:
That was more than I had expected, but ~100ns on a 2018 laptop is very little, especially since error paths are not often hot paths. IMHO performance is not important here except in very special and rare cases. With #1542 using a variable will get flagged; that can catch real errors – I have run into "accidental format string" with that, but never really with fixed strings. This is in the same category as replacing (The case for strconv is a bit stronger, because while most cases don't matter, it's more likely to lead to real measurable performance impact). |
So maybe something for perfsprintf linter ? |
The compiler is optimizing away your benchmark. errors.New gets inlined and the allocation gets optimized away. Try storing the result to a global variable instead of |
My concern isn't the import graph, but the number of direct imports (and thus API made available) in a file. That is, I posit that having only one way of creating errors produces less mental burden than having two. I'm not convinced by performance arguments either way, because the error path isn't the happy path. As for other linters: any linter that wants to suggest replacing calls to errors.New with exported error variables can do the same check for fmt.Errorf with a single argument. |
Ah yeah, of course >_< It's ~31ns. Edited my message. |
Agreed. That was not the reason for my suggestion related to this linter check. My main motivator is from a readability standpoint. I personally find |
Apparently, perfsprintf already reports it catenacyber/perfsprint#27 (comment) I missed it, because I launched golangci-lint, but I missed that a local .golangci.yaml (very basic) file was present in the repository and hadn't perfsprintf enabled. So, perfsprintf reports it already |
Hmm. This seems to actually be triggered now with SA1006 as a call to |
I have seen a lot of code creating errors like
fmt.Errorf("something went wrong")
instead oferrors.New("something went wrong")
. Not only is the latter faster, but I also think that a lot of the former cases are wrong in subtle ways. If you usefmt.Errorf
with a single string and no formatting verbs, you either forgot to add formatting (kind of related to #1528, I guess) or you should have used a regular error instead. As such, I think it be flagged as a problem and suggest replacing the call. In the case where you don't want to wrap or format anything, I also think it is a lot clearer to see a regularerrors.New()
as I can easily know that it is a static error string.The text was updated successfully, but these errors were encountered: