Live data from Hacker News

Go best practices, six years in (2016)

peter.bourgon.org

21–30 of 66 posts

Re: Go best practices, six years in (2016)

#21
post #9

At [Kolide]( https://kolide.com/ ) we're heavy users of Go Kit, and as a result have also adopted a lot of the style Peter recommends here. We've been slowly expanding on it with a style guide and company specific set of common libraries [here]( https://github.com/kolide/kit#kolide-kit ). My coworker also wrote a [blog post]( https://blog.kolide.com/using-go-for-scalable-operating-syst... ) on how Go has been fantast…

I feel like go-kit is quite antithetical to the Go mindset...it presents a lossy abstraction as a means of future-proofing against eventualities that will almost certainly never be encountered to be honest it strikes me as the sort of library that excites intermediate developers who tend to over-architect

I vouched for this comment - why would it deserve to be flagged?

Re: Go best practices, six years in (2016)

#23
post #21

Earlier quoted context omitted.

I feel like go-kit is quite antithetical to the Go mindset...it presents a lossy abstraction as a means of future-proofing against eventualities that will almost certainly never be encountered to be honest it strikes me as the sort of library that excites intermediate developers who tend to over-architect

I vouched for this comment - why would it deserve to be flagged?

This comment in particular wasn't flagged: 'junkscience2017 is banned. Note it was marked [dead], not [flagged].

Re: Go best practices, six years in (2016)

#24
I simply love the go toolchain. The defacto standards for code formatting, linting and vetting, and the speed of builds and tests save tons of time. Both clock time and overall developer productivity.

I have a GitHub CI service that verifies the standard go tools pass on every commit.

The bot itself is naturally written in Go and executed in a Lambda function.

Everything is just so fast! You get feedback in seconds. Which keeps you in the flow of coding.

Maybe some other gophers will find it useful:

https://www.mixable.net/products/bios/

Re: Go best practices, six years in (2016)

#25
post #21

Earlier quoted context omitted.

I feel like go-kit is quite antithetical to the Go mindset...it presents a lossy abstraction as a means of future-proofing against eventualities that will almost certainly never be encountered to be honest it strikes me as the sort of library that excites intermediate developers who tend to over-architect

I vouched for this comment - why would it deserve to be flagged?

[deleted]

Re: Go best practices, six years in (2016)

#26
post #16

Pretty good advice, except the preference for interfaces to support mocking. You should avoid mocking when possible in favor of real objects or fakes. Interfaces are still cool, though.

Can you explain this further, or offer a link that does?

The general theory is that, although you're focused on the code under test, if the underlying dependency is not behaving as expected, you want to know that. Mocks create an opportunity for your code's expectations about your dependencies' behavior to diverge from reality. So if at all possible, they should be avoided.

There are a few general ways to do this. The best way is to use the real underlying dependency. This should be the default.

If the dependency is too slow to use in the test (e.g. it has a long startup time, or is hosted remotely), the next best thing is to use a fake -- a local implementation of the dep that has the same behavior, but operates in memory on ephemeral data. The best libraries will provide these, and if they don't, you might be able to implement one and contribute it back. Even if you have to maintain it yourself, it often takes less code than describing mock behavior. The downside of fakes vs. the real implementation is that their behavior too can diverge. But this is not a net downside compared to mocks.

If you can't use a fake, the next best thing after that is a stub. See below.

Only if none of these options are viable should you use mocks.

(The position I'm describing is the one referred to as "classicist" in this post: https://martinfowler.com/articles/mocksArentStubs.html. I'm not by any means its originator.)

Re: Go best practices, six years in (2016)

#28
post #9

At [Kolide]( https://kolide.com/ ) we're heavy users of Go Kit, and as a result have also adopted a lot of the style Peter recommends here. We've been slowly expanding on it with a style guide and company specific set of common libraries [here]( https://github.com/kolide/kit#kolide-kit ). My coworker also wrote a [blog post]( https://blog.kolide.com/using-go-for-scalable-operating-syst... ) on how Go has been fantast…

I feel like go-kit is quite antithetical to the Go mindset...it presents a lossy abstraction as a means of future-proofing against eventualities that will almost certainly never be encountered to be honest it strikes me as the sort of library that excites intermediate developers who tend to over-architect

> the sort of library that excites intermediate developers

I find this true about nearly all microservices in Go. Microservices are much more useful in something like Node that can only take advantage of 1 OS thread per instance. Without containerization and load balancing in Node you wouldn't be able to scale.

Go on the other hand can efficiently utilize a nearly unlimited amount of threads as necessary with its scheduler. You're much more likely to over-architect if you don't keep this capacity in mind.

Re: Go best practices, six years in (2016)

#29
This is generally great advice, and aside from the package manager recommendations is still relevant today. I do take issue with a few things though.

1. Don't put your internal libraries in /pkg. /pkg has special GOPATH meaning as "compilation cache". Its not an actual name conflict, but why bother risking it.

2. This is just wrong:

> fmt.Printf is self-contained and doesn’t affect or depend on global state; in functional terms, it has something like referential transparency. So it is not a dependency. Obviously, f.Bar is a dependency. And, interestingly, log.Printf acts on a package-global logger object, it’s just obscured behind the free function Printf. So it, too, is a dependency.

stdout (and the buffer, and mutex on it) are exactly the same as the global log object. In fact, `log.Printf` is more or less just an alias to `fmt.Printf`[0]

3. I wish it had mentioned the functional options pattern in the part about constructors[1]

0: https://github.com/golang/go/blob/b77aad089176ecab971d3a72f0...

1: https://dave.cheney.net/2014/10/17/functional-options-for-fr...

Re: Go best practices, six years in (2016)

#30

Pretty good advice, except the preference for interfaces to support mocking. You should avoid mocking when possible in favor of real objects or fakes. Interfaces are still cool, though.

This is straight-up bad advice.

You don't test the http.Client as part of your business logic, even (especially) if your business logic makes HTTP requests. Instead, you trust that package http is already well-tested, mock out http.Client as an abstract HTTP Request Do-er, and you downscope your tests to your business logic exclusively.

Post reply on HN