Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Revive – Fast, configurable, extensible linter for Go (github.com/mgechev)
98 points by angelinaii on June 1, 2018 | hide | past | favorite | 24 comments


Have you looked at golangci-linter [1] at all? It's a competing project that also implement a bunch of linter rules, and was created because gometalinter is too slow.

One reason golangci-linter is faster is that it shares the same in-memory representation of the linted packages between all the linters. From what I can tell, Revive requires that each rule parse the file itself, which is the same design gometalinter use, and it will absolutely kill performance for anything that needs to operate on the full AST.

Also, the Go community does not need a bunch of competing linter tools. For one, at means that tools like Visual Studio Code's Go plugin [2] will have to build special support for each linter tool. Gometalinter was nice because it built lots of rules (including golint) into a single tool, so you just needed that one tool.

I agree with the others about configuration. I think a lint tool should have a configuration work out of the box that reflects Go standards that everyone, without doubt, uses. More controversial conventions such as requiring all exported functions to have comments don't need to be included.

[1] https://github.com/golangci/golangci-lint

[2] https://github.com/Microsoft/vscode-go


Thanks for the comment! Yes, I saw golangci-linter. As the readme of the tool states, it's a linter aggregator, similar to gometalinter, with better performance characteristics. Both golangci-linter and gometalinter incorporate existing tools for static analysis and provide a facade on top.

Revive is a project, which I started about 9 months ago but recently found time to put some finishing touches and open source it. It's not a linter aggregator; it's a framework which provides tools for reducing the friction for development of custom rules for static analysis of your applications.

And no, the individual rules in revive do not parse the files. There's an abstraction on a higher level which parses the files ones. Each rule may request type information for the package which is then cached and reused across the invocations as well. That's how revive manages to improve the performance of golint to this extent.


Thanks for the clarification. I saw the readme, and I assumed (wrongly) that each rule just receive a file name.

I wonder where you draw the line between a "linter aggregator" and a "linter". golangci-lint incorporates all the rules themselves, though it imports the linter logic as libraries, so I'm not sure that it's fair to call it an aggregator. Gometalinter runs linters as child processes and I don't think it contains any linter code, so it's a pure aggregator.

My point is that while your project is admirable, the Go world isn't large enough for so many linter projects. Personally, I just want one good linter that is maintained and that incorporates all the rules I want.


Upvote for mentioning vscode-go which is amazing!


I ment "upvoted"


This really irks me for some reason. One of the goals of the Go tooling in general is to cut down on the number of config files and differing choices that need to be made everywhere.

Gofmt is the canonical example (there is no configuration. It formats things like how Go code is formatted), but almost all of the go tooling sticks to similar principles and its fantastic IMO. No more pointless arguments about style because your config file doesn't match your coworkers, but you both have great reasons for why your configuration is the right one.

I guess it's less a problem with linting, so long as your local configuration is more strict than any run during CI, or other validation steps, but still, in this case I'd prefer to have less control to match the rest of the ecosystem.


Couldn't agree more. The Go toolchain has been the ultimate bikeshed destroyer.

I've always been fond of the Golden Rule for code style: "All code in your project should look as if it was written by one and only one person". The Go toolchain starts you a long way down that road out of the box, with no option to even try to reignite the indent wars, or to slaughter more goats at the altar of the One True Brace. Instead, you get to focus entirely on how that rule applies to language idioms straight away, which is far more meaningful than the colour of the bikeshed or the number of spaces around an operator.

Adding linters is cool, but taking them away directly compromises that property, which I now consider far too valuable to lose.


Thanks for sharing your thoughts! Although the linter is configurable, by default it has the exact same behavior as golint.

The configurability is mostly due to allow developers to extend the tool with custom rules.

Allowing this gives the option to enforce even more opinionated style guide within an organization.

In fact, this is the main purpose of the tool - to provide a framework for static analysis and reduce the friction for creating custom rules.


I believe the customization/custom rules being touted is exactly what the commenter was complaining about; each person creating their own custom rules and then getting upset when others don't do the same. Honoring the spirit of Go, this is not.


> Honoring the spirit of Go, this is not.

Disagree. Some things the Go team just could not justify putting in their checker, such as line lengths. So long as you only add restrictions and don't take any away, you are still honoring the spirit, you just acknowledge that your org may be even more stringent.


There's a core set of rules, which was wisely introduced by the Go team as part of golint. They are all generic practices which are widely adopted.

On the other hand, there are domain-specific problems which can be solved with static analysis as well. They don't have to be style-related, they don't have to be as generic as the ones in golint, they can be on an organization or a project level.

It is often convenient to invest in tooling and automate some manual, error-prone parts of the code review process, whenever possible.

Of course, I'm not implying that everyone should proceed this way. Not all organizations can afford to invest that much time in infrastructure, nor it's necessary. That's mostly a matter of personal choice and priorities.


so long ask you can only add stricter rules and now disable any existing rules, I guess that would be ok. The cost will still conform to a common community style.

It should also disable an added rule if that rule conflicts with some new rule added by the community.


This boogeyman of "pointless arguments" is so strange.

Other than on the internet, I've never experienced pointless bikeshed arguments. So long as within an organization you keep the same standards, what difference does it make? Everywhere I've worked does this and it's fine - and allows us to be break from patterns handed down to us from people doing a different job.


That's your anecdata though, mine's very very different indeed. Many of the places I've worked have either actively fought attempts to get some consistency in place, or have lapsed into total anarchy, even in some cases with edit wars showing up in the Git history. It's horrible, and I'm glad you've been able to avoid it. Go's way is better - those things just can't happen.

There's a network effect too. Sooner or later you'll start to notice that not only does all your organisation's code look consistent, dependencies you pull in look extremely consistent too, as if other organisations were following the same interpretation of the Golden Rule yours is following.

This has enormous benefits when you're assessing the quality of a dependency because once again, you get to walk straight past the same thousand pointless and distracting arguments you got to walk past internally (well, not you of course, but those of us who have been stuck having them!) and get right to the meat of the quality of the code you're assessing for inclusion. "Are the idioms sensible? Are the errors being propagated correctly? Is the public API neat and tidy?" That stuff, the real stuff, is all visible much more quickly when you're not rage-twitching because some other developer from some other team on the other side of the world likes to put the curly brace on a new line at the same indent level as the function body.

I had never experienced this unique benefit with any language ecosystem I worked with before Go and I'm loath to leave it behind. I'm incredibly heartened to see tools like Prettier and Black making strides in the Javascript and Python communities respectively.


Because enforcing it within a reasonably sized organization is still a tall problem. I can't even be trusted to follow my own style preferences from time to time. All it takes is one rogue new employee who doesn't know better and now we have to rehash the same arguments again to teach them a lesson - and the lesson is rarely "this other way is better", it usually boils down to "just do it our way and shut up about it".


Really? Just have your CI reject builds that don't lint...


Exactly this. The beautiful thing about machine checked formatting and linting is that it's consistent, and the ask to conform to it is generally not onerous. If someone wants to make that the hill they die on, I would argue you're now into culture-fit issues with the employee not the process.

This is, in sharp contrast I would add, to all my experience with code-reviews where colleagues are making style criticisms at the same time, which is an utterly useless experience that devalues the entire code review activity.


Nope, the point is that it's a global assumption, we did this "customer to my org" thing with C and C++ already, time to move on.


Forget that. There's example code in the standard library documentation that golint will flag. Seriously. And the devs don't give a fig, even though the "proper" way forces you to put some throwaway variable outside the if statement scope.

Golint literally suggests scope pollution. It deserves to be replaced.


Except gofmt doesn't format everything the same way. It's possible to write some equivalent syntax in different ways. It's irksome that people say it's consistent when it is not.


I understand the use of linters in interpreted languages. But I'd rather see this kind of stuff done as compiler warnings in compiled languages.

Ideally, one could configure the compiler to treat specified warnings as errors and fail the build if they are fired.


Excellent point! The type systems verify programs' correctness based on given specification. On the other hand, we have formatters. Gofmt does a great job in formatting source code so it's consistent and easy to read.

Somewhere between code formatting and type checking, there's another area which unfortunately doesn't fit in any of these two categories. For example, enforcement of style-related practices fits here but it doesn't necessarily take the entire space. That's a broad spectrum.

Revive let you develop rules which can use the Go's type system to provide style suggestions with a confidence level (just like golint), or even domain-specific rules which aim to automate other parts of the code-review process.

Such rules will often produce warnings (suggestions to developers), rather than compile-time errors.


No, please not! It is a feature of the Go compiler, that it does not produce warnings.


We already have go fmt, vet, and integrated vet in go test. thumbs down




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: