Peter Bourgon, a Go developer and author of Go kit, writes about Go best practices, observability, and dependency management.
HN commenters list him among favorite blogs and discuss his Go posts on compatibility and dependencies, including advice against build tags for integration tests.
Go modules is exactly the reference case, but let me expand on that a smidge, because that was when this become crystal-clear to me.
There's one exchange in a blog post linked from the article[1] about dep/modules that I think is illustrative of the entire issue (double >> are quotes in the article from Google/go, single > are commentary from the linked blog author):
>>Although it was a successful experiment, Dep is not the right approach for the next decade of Go development. It has many very serious problems. A few:
>>Dep does not support using multiple major versions of a program in a single build. This alone is a complete showstopper. Go is meant for large-scale work, and in a large-scale program different parts will inevitably need different versions of some isolated dependency.
>Russ [a member of the Go team] has asserted this from day one, and has brought several examples out in evidence, but has simply not convinced the committee that it’s true. Calling it a serious problem, let alone a showstopper, is a significant overstatement. The strongest claim that can be made on this point is that it’s a matter of opinion.
That, to me, is that. Go is Google's language, and Google said that for them, not supporting multiple versions of a dependency was a showstopper. The community read that and saw it as a point for debate, and the author continues to try to debate it in the article.
And that's the issue! It was not a point for debate. Google was being forthright. Google…
I don't know the real relationship between Google and Go, but Go is very much a product of its current core team, who are (AFAIK) all veterans of Bell Labs (Robert Griesemer?) and all have the same Bell Labs approach.
Bell Labs invented Not Invented Here syndrome. You can know this to be true because there is no way this group of people could have the syndrome so bad any other way. The other side of the coin is that they are very, very good. You can know that because they do a lot of interesting, novel work without obviously (or obviously without) having looked at any other research in that field.
Take for example, Chris's comment, "(The most clear and obvious illustration of this is what happened with Go modules, where one member of Google's Go core team discarded the entire system the outside Go community had been working on in favour of a relatively radically different model. See eg for one version of this history.)"
The second link there is to https://peter.bourgon.org/blog/2018/07/27/a-response-about-dep-and-vgo.html.[^1][^2] From that: "[RSC and the dep-pies] discussed dep at the GopherCon contributor summit. Matt Farina says that [Russ Cox] said [he] could do better if [he] went off on [his] own and built something. ... The clear impression was that Russ wasn’t going to engage with the committee, the research [the committee] had prepared for him, or the prototype product of that research, dep — at least, not yet. The clear impression was that Russ had his own…
My first resources were the Go website, specifically the following pages/articles: How to Write go Code [1], Effective Go [2] and Frequently Asked Questions [3].
I also read Alan Donovan and Brian Kerninghan's book "The Go Programming Language" [4]. So mostly these four, and of course simply writing code (along with the standard library documentation [5]).
Since then I've also gained a lot of info and insight from various articles and blogs, such as "Debugging Performance Issues in Go Programs" [6] from an Intel blog, various posts from Peter Bourgon's blog [7] and Dave Cheney's blog [8], both of which I highly recommend. Oh, and "The complete guide to Go net/http timeouts" from the Cloudflare blog [9] is also worth reading.
Previously I was mostly a Perl developer, but I also work(ed) a lot with JavaScript, and to a (much) less extent with Haskell, Racket and Nim.
[1] https://golang.org/doc/code.html
[2] https://golang.org/doc/effective_go.html
[3] https://golang.org/doc/faq
[4] http://www.gopl.io/
[5] https://golang.org/pkg/
[6] https://software.intel.com/en-us/blogs/2014/05/10/debugging-performance-issues-in-go-programs
[7] https://peter.bourgon.org/articles/
[8] https://dave.cheney.net/
[9] https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/
> I'm an engineer too
Yep! Point is, we all are, so we all have to worry about how things break in practice, not only about the theoretical model of compatibility.
And it turns out we break each others' code lots of ways, sometimes even just changing behavior without touching the API. If I had a tool that detected certain build-time problems and worked around others, I could still end up upgrading to a new version of a library that breaks my product. So we end up with vendoring and such where product maintainers sort it out, and probably will continue to need some humans in the loop as long as releases have bugs.
I do think there's plenty to do on the larger issue of compatibility even if not specifically focused on this particular build-time break. There are tools I'd love to see, e.g. to test my program with its deps updated and maybe even do something git-bisect-ish to find just where things went wrong. (Node has something along those lines named Greenkeeper.) Peter Bourgon's got a group working on Go package management, and there's been work done, both practical (e.g. the tools and practices at https://peter.bourgon.org/go-best-practices-2016/#dependency-management) and theoretical (https://research.swtch.com/version-sat). Useful progress and interesting stuff.
I don't think it would be fair to say that the Go community optimizes for productivity over good software development practices. In fact, there's been a good push in the community lately to talk about application design and what it means for code to be good/not good.
* https://github.com/marcusolsson/gouk16-slides/blob/master/building-an-enterprise-service-in-go.pdf
* https://peter.bourgon.org/go-best-practices-2016/
* http://dave.cheney.net/2016/08/20/solid-go-design
However, as a Go developer I'm finding that a lot of examples/tutorials and github projects are taking shortcuts when it comes to program design and how dependencies(loggers, config, db handlers) are being passed around.
https://peter.bourgon.org/go-best-practices-2016/#program-design
IMO it's a sign of Go still being a relatively new language. Despite the language existing for ~6 years now, we're only discovering some best practices today.
Please don't use build tags for integration tests: https://peter.bourgon.org/blog/2021/04/02/dont-use-build-tags-for-integration-tests.html
Along with the issues listed here you will run into issues with editors not building/linting your tests files because they have build tags that the editor is unaware of.
You can also put the environment variable in a TestMain[1] to cover an entire package of integration tests:
func TestMain(m *testing.M)
{
if os.Getenv("RUN_INTEGRATION_TESTS") == ""
{
fmt.Println("Skipping integration tests")
return
}
os.Exit(m.Run())
}
[1] https://pkg.go.dev/testing#hdr-Main