1. 13

  2. 14

    One of the appealing things when first getting into Go was the lack of configuration required for external tools like linters, and just using the built-in gofmt, govet staticcheck and use gopls in your editor.

    Not sure I’d want to run all these in this fashion, but I guess that’s preference.

    1. 1

      Interesting point of view. Yeah, Go works perfectly out of the box and the tooling is also great (sure, there are things that can be better but comparing to other ecosystems it’s definitely better).

      As I mentioned in the post: linters are these small wheels when you’re learning to ride a bike. If you’re ok without them - what is the point to attach configure them?

      By example for most it’s ok to have misspell in the code, for me too mostly. But if I can make my code slightly better for a small price, so why not? :)

      1. 6

        I don’t think it’s just “small wheels when you’re learning how to ride a bike”, because the Go project refuses to add warnings they can’t really add new diagnostics which would break existing code, and there’s a lot of common errors in go code you may want to guard against, which requires a linter.

        E.g. append errors, ignoring error return values, creating interface values from possibly nil typed pointers, closing over loop variables, dead stores, passing locks by value, as well as more defensive practices you may want to impose in larger codebases like full slices, …

        1. 5

          Warnings are added via vet. “closing over loop variables” and “passing locks by value” are both covered. edit: they refuse to add vet warnings that have the potential for false positives.

          1. 5

            Yeah, I can see both sides of this:

            • We refuse to use warnings to the compiler because programmers just ignore warnings!
            • Well, we can’t make this in an error in the compiler, so we’ll make it an error in go vet.
            • Now go vet is effectively -WAll and everyone needs to run it to ensure correctness.
            • We can’t add warnings to go vet because then programmers would just ignore them!

            Rinse and repeat. :-)

            1. 5

              I think it’s more subtle than that. I think Go situation is isomorphic to Rust.

              In Rust, compiler emits errors and warnings. False positives are not allowed. New warnings for old code are added over time. This creates a problem that, if you deny warnings during a build, and warning in dependency can lock you out of a new compiler. For this reason rust has a special flag which tells it to emit warnings in user’s own code, but not in dependencies. So, errors are for all code, warnings are for your code.

              Go does exactly the same thing, except that it’s a separate subcommand (vet) rather than a special flag for the compiler.

          2. 4

            Totally agree. There are so many errors in Go that are only caught by the linter and not the compiler. The linter is necessary.

            1. 1

              Many of the things discussed here, and elsewhere, are actually highlighted by Goland, which is one reason I’m a loyal JetBrains user.

        2. 2

          the right configuration is go vet/go lint/staticcheck

          golangci-lint is a bunch of nonsense

          1. 3

            This sounds a bit inflammatory. For the benefits of us beginners, why do you consider that those tools are the right thing and golangci-lint should be avoided?

            1. 5

              One example: golangci-lint includes a linter called ireturn which warns when you return interface types from functions. It references Rob Pike’s opinion on the proverb “Accept Interfaces Return Struct/Concrete Types”. To which he responded

              I’m not a great fan of that one. It’s subtle and tricky to explain compactly. And although popular, it’s not often easy to apply well. Plus: Why structs? There are many other concrete types in Go […] It’s very hard to be clear about where it applies, and it often doesn’t.

              It’s a bit comical that this manufactured lint rule appeals to authority by linking to a Rob Pike conversation … which ultimately disagrees with the proverb that influenced the lint rule.

              Linter rules are a bunch of opinions that aren’t agreed upon, while native go tools are for better or worse the “law of the land”. Nobody will ask you to love the law, but you’ll abide by it as long as it remains unchanged.

              1. 3

                That has nothing to do with avoiding golangci-lint though. That they have a lint available doesn’t mean you have to use that lint, as can be seen by TFA disabling a bunch of them.

                And that something is a compiler error doesn’t mean everyone agrees with it, just that whoever wanted it got it through before the language was published.

                Furthermore the existence of go vet completely breaks your quip by both being “a buch of opinions that aren’t agreed upon” (because it’s a linter) and “the law of the land” (because it’s a native go tool).

                1. 2

                  I’ll gladly concede that go vet is a linter and won’t bother arguing my ill defined concept of “land law” with respect to its checks :)

                  However every compiler error is indisputably the law of the land. Because you can disagree with compiler errors all day long, but without changing the compiler, any argument against them is moot. There is a high barrier to changing compiler errors; in that sense they are very much law.

                  As I said:

                  you’ll abide by it as long as it remains unchanged.

                  1. 1

                    the fact that you need to disable lints is a problem with the tool.

                2. 3

                  there are many issues with it, however the primary problem is that it bundles an old fork of staticcheck and disables many of their default lints. it also includes a bunch of linters that don’t really do anything.

                  here is one of several instances I know of from the staticcheck maintainer on twitter and I don’t even pay that much attention, I’m sure if you searched golangci-lint on the staticcheck issue tracker you’d find more

                  1. -2

                    Sounds like a weak way to promote own tool. Just saying.

                    1. 3

                      I’m not the maintainer, however, I feel sympathy for him. that being said, golangci-lint isn’t doing anything wrong or illegal, it’s open source software, you’re free to use it even in ways the original author doesn’t intend or approve of. that being said, you aren’t necessarily entitled to support

                      1. 3

                        This is no way to conduct yourself in public.

                        1. 1

                          Sounds like a weak way to promote own tool. Just saying.

                          Not a very charitable take.

                          I don’t know anything about the specifics of that debate, and I haven’t (yet?) noticed problems using staticcheck with golangci-lint. But when I started using golangci-lint in December of last year, I immediately noticed that the results for revive were different if I used it under golangci-lint than if I used it alone. (Briefly, revive under golangci-lint was silent where there should have been warnings.) The problem persisted, and I ended up with this note in a git commit.

                          At the moment, the revive and golangci configurations are separate, and
                          they have some overlap. They don't seem to play nicely together, and
                          I don't want to spend too much time debugging that now. But I should
                          come back to this later.

                          As you can imagine, I never came back to it. The only way that I can get things to work correctly is (still) that I run revive alone and then I run golangci-lint for the rest of the linters I use. That’s not the end of the world, but it does suggest to me that the staticcheck maintainer is not making things up. golangci-lint seems to alter how (some?) tools operate under it. That may make sense—or even be necessary for some reason—but it can also be a pain. I like golangci-lint a lot, but it causes some problems too.