The current Go language memory model was written in 2009, with minor updates since. It is clear that there are at least a few details that we should add to the current memory model, among them an explicit endorsement of race detectors and a clear statement of how the APIs in sync/atomic synchronize programs.

This post restates Go’s overall philosophy and the current memory model and then outlines the relatively small adjustments I believe that we should make to the Go memory model. It assumes the background presented in the earlier posts “Hardware Memory Models” and “Programming Language Memory Models.”

I have opened a GitHub discussion to collect feedback on the ideas presented here. Based on that feedback, I intend to prepare a formal Go proposal later this month. The use of GitHub discussions is itself a bit of an experiment, continuing to try to find a reasonable way to scale discussions of important changes.

Read More

To kick things off, why are constants good? Three things spring to mind:

  • Immutability. Constants are one of the few ways we have in Go to express immutability to the compiler.

  • Clarity. Constants give us a way to extract magic numbers from our code, giving them names and semantic meaning.

  • Performance. The ability to express to the compiler that something will not change is key as it unlocks optimisations such as constant folding, constant propagation, branch and dead code elimination.

But these are generic use cases for constants, they apply to any language. Let’s talk about some of the properties of Go’s constants.

Read More

Go’s place between C and Python in terms of abstraction and garbage collection memory management model has made it attractive to programmers looking for a fast but reasonably high level language. However, there is no free lunch. Go’s abstractions, especially with regards to allocation, come with a cost. This article will show ways to measure and reduce this cost.

A change recently landed in the development version of Go, and will be in Go 1.17, with the title of doc/go1.17: note deprecation of ‘go get’ for installing commands. The actual updated documentation (from the current draft release notes) says:

go get prints a deprecation warning when installing commands outside the main module (without the -d flag). go install cmd@version should be used instead to install a command at a specific version, using a suffix like @latest or @v1.2.3. In Go 1.18, the -d flag will always be enabled, and go get will only be used to change dependencies in go.mod.

I have some views on this. The first one is that this is a pretty abrupt deprecation schedule. Go will be printing a warning for only one release, which means six months or so. People who don’t update to every Go version (or their operating system’s packaged version doesn’t) will go from ‘go get’ working normally to install programs to having it fail completely.

Read More

I’ve spent a lot of time thinking about the best way to handle errors in Go programs. I really wanted there to be a single way to do error handling, something that we could teach all Go programmers by rote, just as we might teach mathematics, or the alphabet.

However, I have concluded that there is no single way to handle errors. Instead, I believe Go’s error handling can be classified into the three core strategies.

If you’ve worked with Go before, you’ve probably seen this runtime error.

panic: runtime error: invalid memory address or nil pointer dereference

The current solution is checking thevar != nil before using the var, but forgetting to do that means your program will crash. That means this simple programmer error could take down your whole server. Hopefully you catch these errors with tests before they reach production. However, we’re not machines so inevitably we won’t catch some of these until our end users encounter an error in production.

Read More

I’m learning Go as a first language, is there any use cases where I should avoid Go?

The release of Go 1.16 introduced a new embed package in the Go standard library. It provides access to files embedded in a Go program at compile time using the new //go:embed directive. It’s a powerful new feature because it allows building a binary with static dependencies like templates, HTML/CSS/JS, or images self-contained. This portability is great for easy distribution and usage. Previously, developers had to rely on third-party libraries for embed behaviour.

In this article we’ll walk through a small demo app, golang-nextjs-portable, that exposes an HTTP server that hosts both an API endpoint, as well as an embedded (Next.js) web app that calls the API.

Read More

I like Go. I use it for a number of things (including this blog, at the time of writing). Go is useful. With that said, Go is not a good language. It’s not bad; it’s just not good.

We have to be careful using languages that aren’t good, because if we’re not careful, we might end up stuck using them for the next 20 years.

This is a list of my chief complaints about Go. Some of these are mentioned frequently, and some are rarely discussed.

I’ve also included some comparisons to both Rust and Haskell (which I consider to be good languages). This is to show that all the problems listed here have already been solved.

Read More

We are excited to announce that native fuzzing is ready for beta testing in its development branch, dev.fuzz!

Fuzzing is a type of automated testing which continuously manipulates inputs to a program to find issues such as panics or bugs. These semi-random data mutations can discover new code coverage that existing unit tests may miss, and uncover edge case bugs which would otherwise go unnoticed. Since fuzzing can reach these edge cases, fuzz testing is particularly valuable for finding security exploits and vulnerabilities.

Read More

Today’s post comes from a recent Go pop quiz. Consider this benchmark fragment.1

func BenchmarkSortStrings(b *testing.B) {
        s := []string{“heart”, “lungs”, “brain”, “kidneys”, “pancreas”}
        for i := 0; i < b.N; i++ {

A convenience wrapper around sort.Sort(sort.StringSlice(s)), sort.Strings sorts the input in place, so it isn’t expected to allocate (or at least that’s what 43% of the tweeps who responded thought). However it turns out that, at least in recent versions of Go, each iteration of the benchmark causes one heap allocation. Why does this happen?

Read More

Over the past couple months, I’ve been working on a library for constant-time Big Numbers in Go. I think it’s about time that I presented a bit of this work.

In this post, I’ll try to explain what exactly this work is about, and why you might care about it. This post is intended to be an introduction, and shouldn’t require any background in Cryptography.

Nate Finch had a nice blog post on error flags recently, and it caused me to think about error handling in my own greenfield Go project at work.

Much of the Go software I write follows a common pattern: an HTTP JSON API fronting some business logic, backed by a data store of some sort. When an error occurs, I typically want to present a context-aware HTTP status code and an a JSON payload containing an error message. I want to avoid 400 Bad Request and 500 Internal Server Errors whenever possible, and I also don’t want to expose internal implementation details or inadvertently leak information to API consumers.

I’d like to share the pattern I’ve settled on for this type of application.

Read More

Back in December 2019, I first wrote about Goliath, Khan Academy’s project to migrate our backend from a Python 2 monolith to services written in Go, along with other changes needed to make that journey. I also wrote about how we’re making this change as incrementally as can be.

When we started Goliath, no one on the team knew Go beyond the experiments we ran to validate that Go would be a better choice for us than our other options. Today, all of our backend and full-stack engineers write Go, and our incremental delivery of Goliath has vaulted us over a big milestone: More than 500,000 lines of Go now running in production. This seemed like a good point to reflect on Go itself.

Read More

This article presents Mugo, a single-pass compiler for a tiny subset of the Go programming language. It outputs (very naive) x86-64 assembly, and supports just enough of the language to implement a Mugo compiler: int and string types, slices, functions, locals, globals, and basic expressions and statements.

This post is a basic introduction to running HTTPS servers and clients in Go using TLS. It assumes some familiarity with public-key crypto. Feel free to check out my earlier posts about RSA and the Diffie-Hellman Key Exchange; TLS uses the elliptic-curve version of Diffie-Hellman. I won’t be covering how the protocol itself works in detail here, but if you’re interested I recommend to read up on the subject.

No software is perfect, and thus even for software I find very pleasant, I can usually identify some problems in it — often using my blog to do so. Even my all-time favorite software project, Plan 9, has some painful flaws! For some projects, it may be my fondness for them that drives me to criticise them even more, in the hope that they’ll live up to the level of respect I feel for them.

One such project is the Go programming language. I have had many criticisms, often shared on this blog and elsewhere, but for the most part, my praises have been aired mainly in private. I’d like to share some of those praises today, because despite my criticisms of it, Go remains one of the best programming languages I’ve ever used, and I have a great deal of respect for it.

Read More

Discuss the Go programming language.

Created on Oct 1, 2020
By @root