{"id":1404,"date":"2017-08-29T09:31:47","date_gmt":"2017-08-29T01:31:47","guid":{"rendered":"https:\/\/www.strongd.net\/?p=1404"},"modified":"2017-08-29T09:38:52","modified_gmt":"2017-08-29T01:38:52","slug":"why-go-is-my-favorite-programming-language","status":"publish","type":"post","link":"https:\/\/www.strongd.net\/?p=1404","title":{"rendered":"Why Go is my favorite programming language"},"content":{"rendered":"<p>I strive to respect everybody\u2019s personal preferences, so I usually steer clear of debates about which is the best programming language, text editor or operating system.<\/p>\n<p>However, recently I was asked a couple of times why I like and use a lot of\u00a0<a href=\"https:\/\/golang.org\/\">Go<\/a>, so here is a coherent article to fill in the blanks of my ad-hoc in-person ramblings :-).<\/p>\n<h3 id=\"my-background\">My background<\/h3>\n<p>I have used C and Perl for a number of decently sized projects. I have written programs in Python, Ruby, C++, CHICKEN Scheme, Emacs Lisp, Rust and Java (for Android only). I understand a bit of Lua, PHP, Erlang and Haskell. In a previous life, I developed a number of programs using\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Delphi_(programming_language)\">Delphi<\/a>.<\/p>\n<p>I had a brief look at Go in 2009, when it was first released. I seriously started using the language when Go 1.0 was released in 2012, featuring the\u00a0<a href=\"https:\/\/golang.org\/doc\/go1compat\">Go 1 compatibility guarantee<\/a>. I still have\u00a0<a href=\"https:\/\/github.com\/stapelberg\/greetbot\">code<\/a>\u00a0running in production which I authored in 2012, largely untouched.<\/p>\n<h3 id=\"1-clarity\">1. Clarity<\/h3>\n<h4 id=\"formatting\">Formatting<\/h4>\n<p>Go code, by convention, is formatted using the\u00a0<a href=\"https:\/\/golang.org\/cmd\/gofmt\/\"><code class=\"highlighter-rouge\">gofmt<\/code><\/a>\u00a0tool. Programmatically formatting code is not a new idea, but contrary to its predecessors,\u00a0<code class=\"highlighter-rouge\">gofmt<\/code>\u00a0supports precisely one canonical style.<\/p>\n<p>Having all code formatted the same way makes reading code easier; the code feels familiar. This helps not only when reading the standard library or Go compiler, but also when working with many code bases \u2014 think Open Source, or big companies.<\/p>\n<p>Further, auto-formatting is a huge time-saver during code reviews, as it eliminates an entire dimension in which code could be reviewed before: now, you can just let your continuous integration system verify that\u00a0<code class=\"highlighter-rouge\">gofmt<\/code>\u00a0produces no diffs.<\/p>\n<p>Interestingly enough, having my editor apply\u00a0<code class=\"highlighter-rouge\">gofmt<\/code>\u00a0when saving a file has changed the way I write code. I used to attempt to match what the formatter would enforce, then have it correct my mistakes. Nowadays, I express my thought as quickly as possible and trust\u00a0<code class=\"highlighter-rouge\">gofmt<\/code>\u00a0to make it pretty (<a href=\"https:\/\/play.golang.org\/p\/I6GJwiT77v\">example<\/a>\u00a0of what I would type, click Format).<\/p>\n<h4 id=\"high-quality-code\">High-quality code<\/h4>\n<p>I use the standard library (<a href=\"https:\/\/golang.org\/pkg\/\">docs<\/a>,\u00a0<a href=\"https:\/\/github.com\/golang\/go\/tree\/master\/src\">source<\/a>) quite a bit, see below.<\/p>\n<p>All standard library code which I have read so far was of extremely high quality.<\/p>\n<p>One example is the\u00a0<a href=\"https:\/\/golang.org\/pkg\/image\/jpeg\/\"><code class=\"highlighter-rouge\">image\/jpeg<\/code><\/a>\u00a0package: I didn\u2019t know how JPEG worked at the time, but it was easy to pick up by switching between the\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/JPEG\">Wikipedia JPEG article<\/a>\u00a0and the<code class=\"highlighter-rouge\">image\/jpeg<\/code>\u00a0code. If the package had a few more comments, I would qualify it as a teaching implementation.<\/p>\n<h4 id=\"opinions\">Opinions<\/h4>\n<p>I have come to agree with many opinions the Go community holds, such as:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/golang\/go\/wiki\/CodeReviewComments#variable-names\">Variable names<\/a>\u00a0should be short by default, and become more descriptive the further from its declaration a name is used.<\/li>\n<li>Keep the dependency tree small (to a reasonable degree):\u00a0<a href=\"https:\/\/www.youtube.com\/watch?v=PAAkCSZUG1c&amp;t=9m28s\">a little copying is better than a little dependency<\/a><\/li>\n<li>There is a cost to introducing an abstraction layer. Go code is usually rather clear, at the cost of being a bit repetitive at times.<\/li>\n<li>See\u00a0<a href=\"https:\/\/github.com\/golang\/go\/wiki\/CodeReviewComments\">CodeReviewComments<\/a>\u00a0and\u00a0<a href=\"https:\/\/go-proverbs.github.io\/\">Go Proverbs<\/a>\u00a0for more.<\/li>\n<\/ul>\n<h4 id=\"few-keywords-and-abstraction-layers\">Few keywords and abstraction layers<\/h4>\n<p>The Go specification lists only\u00a0<a href=\"https:\/\/golang.org\/ref\/spec#Keywords\">25 keywords<\/a>, which I can easily keep in my head.<\/p>\n<p>The same is true for\u00a0<a href=\"https:\/\/golang.org\/pkg\/builtin\/\">builtin functions<\/a>\u00a0and\u00a0<a href=\"https:\/\/golang.org\/ref\/spec#Types\">types<\/a>.<\/p>\n<p>In my experience, the small number of abstraction layers and concepts makes the language easy to pick up and quickly feel comfortable in.<\/p>\n<p>While we\u2019re talking about it: I was surprised about how readable the\u00a0<a href=\"https:\/\/golang.org\/ref\/spec\">Go specification<\/a>\u00a0is. It really seems to target programmers (rather than standards committees?).<\/p>\n<h3 id=\"2-speed\">2. Speed<\/h3>\n<h4 id=\"quick-feedback--low-latency\">Quick feedback \/ low latency<\/h4>\n<p>I love quick feedback: I appreciate websites which load quickly, I prefer fluent User Interfaces which don\u2019t lag, and I will choose a quick tool over a more powerful tool any day.\u00a0<a href=\"https:\/\/blog.gigaspaces.com\/amazon-found-every-100ms-of-latency-cost-them-1-in-sales\/\">The findings<\/a>\u00a0of large web properties confirm that this behavior is shared by many.<\/p>\n<p>The authors of the Go compiler respect my desire for low latency: compilation speed matters to them, and new optimizations are carefully weighed against whether they will slow down compilation.<\/p>\n<p>A friend of mine had not used Go before. After installing the\u00a0<a href=\"https:\/\/robustirc.net\/\">RobustIRC<\/a>\u00a0bridge using\u00a0<code class=\"highlighter-rouge\">go get<\/code>, they concluded that Go must be an interpreted language and I had to correct them: no, the Go compiler just is that fast.<\/p>\n<p>Most Go tools are no exception, e.g.\u00a0<code class=\"highlighter-rouge\">gofmt<\/code>\u00a0or\u00a0<code class=\"highlighter-rouge\">goimports<\/code>\u00a0are blazingly fast.<\/p>\n<h4 id=\"maximum-resource-usage\">Maximum resource usage<\/h4>\n<p>For batch applications (as opposed to interactive applications), utilizing the available resources to their fullest is usually more important than low latency.<\/p>\n<p>It is delightfully easy to profile and change a Go program to utilize all available IOPS, network bandwidth or compute. As an example, I wrote about\u00a0<a href=\"https:\/\/people.debian.org\/~stapelberg\/2014\/01\/17\/debmirror-rackspace.html\">filling a 1 Gbps link<\/a>, and optimized\u00a0<a href=\"https:\/\/github.com\/Debian\/debiman\/\">debiman<\/a>\u00a0to utilize all available resources, reducing its runtime by hours.<\/p>\n<h3 id=\"3-rich-standard-library\">3. Rich standard library<\/h3>\n<p>The\u00a0<a href=\"https:\/\/golang.org\/pkg\">Go standard library<\/a>\u00a0provides means to effectively use common communications protocols and data storage formats\/mechanisms, such as TCP\/IP, HTTP, JPEG, SQL, \u2026<\/p>\n<p>Go\u2019s standard library is the best one I have ever seen. I perceive it as well-organized, clean, small, yet comprehensive: I often find it possible to write reasonably sized programs with just the standard library, plus one or two external packages.<\/p>\n<p>Domain-specific data types and algorithms are (in general) not included and live outside the standard library, e.g.\u00a0<a href=\"https:\/\/godoc.org\/golang.org\/x\/net\/html\"><code class=\"highlighter-rouge\">golang.org\/x\/net\/html<\/code><\/a>. The\u00a0<code class=\"highlighter-rouge\">golang.org\/x<\/code>\u00a0namespace also serves as a staging area for new code before it enters the standard library: the Go 1 compatibility guarantee precludes any breaking changes, even if they are clearly worthwhile. A prominent example is\u00a0<code class=\"highlighter-rouge\">golang.org\/x\/crypto\/ssh<\/code>, which had to break existing code to\u00a0<a href=\"https:\/\/github.com\/golang\/crypto\/commit\/e4e2799dd7aab89f583e1d898300d96367750991\">establish a more secure default<\/a>.<\/p>\n<h3 id=\"4-tooling\">4. Tooling<\/h3>\n<p>To download, compile, install and update Go packages, I use the\u00a0<code class=\"highlighter-rouge\">go get<\/code>\u00a0tool.<\/p>\n<p>All Go code bases I have worked with use the built-in\u00a0<a href=\"https:\/\/golang.org\/pkg\/testing\/\"><code class=\"highlighter-rouge\">testing<\/code><\/a>\u00a0facilities. This results not only in easy and fast testing, but also in\u00a0<a href=\"https:\/\/blog.golang.org\/cover\">coverage reports<\/a>\u00a0being readily available.<\/p>\n<p>Whenever a program uses more resources than expected, I fire up\u00a0<code class=\"highlighter-rouge\">pprof<\/code>. See this\u00a0<a href=\"https:\/\/blog.golang.org\/profiling-go-programs\">golang.org blog post about\u00a0<code class=\"highlighter-rouge\">pprof<\/code><\/a>\u00a0for an introduction, or\u00a0<a href=\"https:\/\/people.debian.org\/~stapelberg\/2014\/12\/23\/code-search-taming-the-latency-tail.html\">my blog post about optimizing Debian Code Search<\/a>. After importing the\u00a0<a href=\"https:\/\/golang.org\/pkg\/net\/http\/pprof\/\"><code class=\"highlighter-rouge\">net\/http\/pprof<\/code>\u00a0package<\/a>, you can profile your server while it\u2019s running, without recompilation or restarting.<\/p>\n<p>Cross-compilation is as easy as setting the\u00a0<code class=\"highlighter-rouge\">GOARCH<\/code>\u00a0environment variable, e.g.\u00a0<code class=\"highlighter-rouge\">GOARCH=arm64<\/code>\u00a0for targeting the Raspberry Pi 3. Notably, tools just work cross-platform, too! For example, I can profile\u00a0<a href=\"https:\/\/gokrazy.org\/\">gokrazy<\/a>\u00a0from my amd64 computer:\u00a0<code class=\"highlighter-rouge\">go tool pprof ~\/go\/bin\/linux_arm64\/dhcp http:\/\/gokrazy:3112\/debug\/pprof\/heap<\/code>.<\/p>\n<p><a href=\"https:\/\/godoc.org\/golang.org\/x\/tools\/cmd\/godoc\">godoc<\/a>\u00a0displays documentation as plain text or serves it via HTTP.\u00a0<a href=\"https:\/\/godoc.org\/\">godoc.org<\/a>\u00a0is a public instance, but I run a local one to use while offline or for not yet published packages.<\/p>\n<p>Note that these are standard tools coming with the language. Coming from C, each of the above would be a significant feat to accomplish. In Go, we take them for granted.<\/p>\n<h3 id=\"getting-started\">Getting started<\/h3>\n<p>Hopefully I was able to convey why I\u2019m happy working with Go.<\/p>\n<p>If you\u2019re interested in getting started with Go, check out\u00a0<a href=\"https:\/\/github.com\/gopheracademy\/gopher\/blob\/1cdbcd9fc3ba58efd628d4a6a552befc8e3912be\/bot\/bot.go#L516\">the beginner\u2019s resources<\/a>\u00a0we point people to when they join the Gophers slack channel. See\u00a0<a href=\"https:\/\/golang.org\/help\/\">https:\/\/golang.org\/help\/<\/a>.<\/p>\n<h3 id=\"caveats\">Caveats<\/h3>\n<p>Of course, no programming tool is entirely free of problems. Given that this article explains why Go is my favorite programming language, it focuses on the positives. I will mention a few issues in passing, though:<\/p>\n<ul>\n<li>If you use Go packages which don\u2019t offer a stable API, you might want to use a specific, known-working version. Your best bet is the\u00a0<a href=\"https:\/\/github.com\/golang\/dep\">dep<\/a>\u00a0tool, which is not part of the language at the time of writing.<\/li>\n<li>Idiomatic Go code does not necessarily translate to the highest performance machine code, and the runtime comes at a (small) cost. In the rare cases where I found performance lacking, I successfully resorted to\u00a0<a href=\"https:\/\/golang.org\/cmd\/cgo\/\">cgo<\/a>\u00a0or assembler. If your domain is hard-realtime applications or otherwise extremely performance-critical code, your mileage may vary, though.<\/li>\n<li>I wrote that the Go standard library is the best I have ever seen, but that doesn\u2019t mean it doesn\u2019t have any problems. One example is\u00a0<a href=\"https:\/\/golang.org\/issues\/20744\">complicated handling of comments<\/a>\u00a0when modifying Go code programmatically via one of the standard library\u2019s oldest packages,\u00a0<code class=\"highlighter-rouge\">go\/ast<\/code>.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I strive to respect everybody\u2019s personal preferences, so I usually steer clear of debates about which is the best programming language, text editor or operating system. However, recently I was asked a couple of times why I like and use a lot of\u00a0Go, so here is a coherent article to fill in the blanks of &hellip; <a href=\"https:\/\/www.strongd.net\/?p=1404\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Why Go is my favorite programming language<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,20],"tags":[216,198],"class_list":["post-1404","post","type-post","status-publish","format-standard","hentry","category-linux","category-20","tag-glang","tag-go"],"_links":{"self":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/1404","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1404"}],"version-history":[{"count":1,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/1404\/revisions"}],"predecessor-version":[{"id":1405,"href":"https:\/\/www.strongd.net\/index.php?rest_route=\/wp\/v2\/posts\/1404\/revisions\/1405"}],"wp:attachment":[{"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1404"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1404"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.strongd.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1404"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}