Dave Cheney | Go
1,309 FOLLOWERS
Go Contributor
Dave Cheney | Go
3y ago
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"}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
sort.Strings(s)
}
}
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 ca ..read more
Dave Cheney | Go
3y ago
The Go compiler’s SSA backend contains a facility to produce HTML debugging output of the compilation phases. This post covers how to print the SSA output for function and methods.
Let’s start with a sample program which contains a function, a value method, and a pointer method:
package main
import (
"fmt"
)
type Numbers struct {
vals []int
}
func (n *Numbers) Add(v int) {
n.vals = append(n.vals, v)
}
func (n Numbers) Average() float64 {
sum := 0.0
for _, num := range n.vals {
sum += float64(num)
}
return sum / float64(len(n.vals))
}
func main ..read more
Dave Cheney | Go
3y ago
Per the overlapping interfaces proposal, Go 1.14 now permits embedding of interfaces with overlapping method sets. This is a brief post explain what this change means:
Let’s start with the definition of the three key interfaces from the io package; io.Reader, io.Writer, and io.Closer:
package io
type Reader interface {
Read([]byte) (int, error)
}
type Writer interface {
Write([]byte) (int, error)
}
type Closer interface {
Close() error
}
Just as embedding a type inside a struct allows the embedded type’s fields and methods to be accessed as if it were declared on ..read more
Dave Cheney | Go
3y ago
A few days ago Fatih posted this question on twitter.
I’m going to attempt to give my answer, however to do that I need to apply some simplifications as my previous attempts to answer it involved a lot of phrases like a pointer to a pointer, and other unhelpful waffling. Hopefully my simplified answer can be useful in building a mental framework to answer Fatih’s original question.
Restating the question
Fatih’s original tweet showed four different variations of json.Unmarshal. I’m going to focus on the last two, which I’ll rewrite a little:
package main
import (
"encoding/json"
"fmt ..read more
Dave Cheney | Go
3y ago
Conventional wisdom dictates that the larger the number of types declared in a Go program, the larger the resulting binary. Intuitively this makes sense, after all, what’s the point in defining a bunch of types if you’re not going to write code that operates on them. However, part of the job of a linker is to detect functions which are not referenced by a program–say they are part of a library of which only a subset of functionality is used–and remove them from the final output. Yet, the adage mo’ types, mo’ binary holds true for the majority of Go programs.
In this post I’ll dig into what equ ..read more
Dave Cheney | Go
3y ago
This is a post about how the Go compiler implements inlining and how this optimisation affects your Go code.
n.b. This article focuses on gc, the de facto Go compiler from golang.org. The concepts discussed apply broadly to other Go compilers like gccgo and tinygo but may differ in implementation and efficacy.
What is inlining?
Inlining is the act of combining smaller functions into their respective callers. In the early days of computing this optimisation was typically performed by hand. Nowadays inlining is one of a class of fundamental optimisations performed automatically during the compil ..read more
Dave Cheney | Go
3y ago
The testing package is one of my favourite packages in the Go standard library, not just because of its low noise approach to unit testing, but, over the lifetime of Go, it has received a steady stream of quality of life improvements driven by real world usage.
The most recent example of this is, in Go 1.14, go test -v will stream t.Log output as it happens, rather than hoarding it til the end of the test run. Here’s an example;
package main
import (
"fmt"
"testing"
"time"
)
func TestLogStreaming(t *testing.T) {
for i := 0; i < 5; i ..read more
Dave Cheney | Go
3y ago
Programmers have a tendency to be superstitious. Particularly, when a programmer hears that copies are expensive, they start to see them everywhere, especially when they learn that, in Go, every assignment is a copy.
Consider this code; x is three orders of magnitude larger than y, is the assignment of x to a more expensive than the assignment of y to b?
func f() {
x, y := make([]byte, 9000), make([]byte, 9)
a := x
b := y
// ...
}
The answer is; no. x and y have the same type, []byte, that is, a slice of bytes. As both variables have the same type, their assignm ..read more