Category Archives: Go

Pointers in Go

This blog post was originally a comment on a Google Plus page, but apparently one cannot create a href to a comment so it was suggested I rewrite it as a blog post.


Go pointers, like C pointers, are values that, uh, point to other values. This is a tremendously important concept and shouldn’t be considered dangerous or something to get hung up on.

Here are several ways that Go improves over C pointers, and C++, for that matter.

  1. There is no pointer arithmetic. You cannot write in Go
    var p *int
    p++

    That is, you cannot alter the address p points to unless you assign another address to it.

  2. This means there is no pointer/array duality in Go. If you don’t know what I’m talking about, read this book. Even if you have no intention of programming in C or Go, it will enrich your life.
  3. Once a value is assigned to a pointer, with the exception of nil which I’ll cover in the next point, Go guarantees that the thing being pointed to will continue to be valid for the lifetime of the pointer. So
    func f() *int { 
            i := 1
            return &i
    }

    is totally safe to do in Go. The compiler will arrange for the memory location holding the value of i to be valid after f() returns.

  4. Nil pointers. Yes, you can still have nil pointers and panics because of them, however in my experience the general level of hysteria generated by nil pointer errors, and the amount of defensive programming present in other languages like Java is not present in Go.

    I believe this is for two three reasons

    1. multiple return values, nil is not used as a sentinel for something went wrong. Obviously this leaves the question of programmers not checking their errors, but this is simply a matter of education.
    2. Strings are value types, not pointers, which is the, IMO, the number one cause of null pointer exceptions in languages like Java and C++.
      var s string // the zero value of s is "", not nil
    3. In fact, most of the built in data types, maps, slices, channels, and arrays, have a sensible default if they are left uninitialized. Thanks to Dustin Sallings for pointing this out.

Using go test, build and install

With one exception, the go command takes arguments in the form of packages.

You can pass the package name(s) explicitly, eg.

go test github.com/hoisie/mustache

or implicitly

cd $GOPATH/src/github.com/hoisie/mustache
go test .

By default, if no arguments are provided go test treats the current directory as a package, so in the second example, go test . is identical in function to

cd $GOPATH/src/github.com/hoisie/mustache
go test

The ability to pass a single file to go {build,test,install} is a degenerate case brought about by go run accepting a single .go file as its argument.

go run should be considered the single exception to the rule outlined above.

A Go client for Joyent Manta

Over the last few weeks I had the opportunity of working with the Joyent folks on the port of Go to Solaris1.

As part of this work I noted that the Joyeurs were using their rather spiffy Manta service for sharing code snippets and build logs. This made the rest of us using Pastebin services feel rather Web 1.0.

So, last weekend I sat down and wrote a simple Manta client in Go. As of this morning the total line count including tests was less than 450 lines. I don’t know how that compares to the Node.js or Java clients, but i’d be willing to bet it is far shorter thanks to the utility of the Go standard library.

Code is on github, https://github.com/davecheney/manta. Also included are implementations of some of the Manta CLI utilities.

Docs are on godoc, http://godoc.org/github.com/davecheney/manta


  1. Our port is actually called sunos/amd64 partly because Aram and I are nostalgic curmudgeons, but mainly because the OS X port of Go is called darwin.

Benchmarking Go 1.2rc5 vs gccgo

I’ve been doing a lot of work with gccgo recently and with the upcoming release of Go 1.2 I’ve also been collecting benchmark results for that release.

Presented below, using a very unscientific method, are the results of comparing the go1 benchmark results for the two compilers.

gc-vs-gccgo

Buried among that see of red are a few telltale signs that the more capable gcc backed optimiser can eek out better arithmetic performance.

As another data point, here is the floats benchmark from my autobench suite, run under the same conditions as above.

floats

I want to be clear that these are very preliminary results, and, like all all micro benchmarks are subject to interpretation.

I also want to stress that I am not dismissing gccgo based on these results. As I understand it gccgo lacks a few key features, such as escape analysis, which is probably responsible for most of the performance loss when the amount of computation is dwarfed by memory bookkeeping.

gccgo is developed largely by one person, ian Taylor, and is a significant achievement. Recently he and Chris Manghane have been working on decoupling the gofrontend code from gcc so it can be reused with other compiler backends, LLVM being the most obvious.

If you are interested in contributing to Go, please don’t forget about gccgo, or even llgo as possible outlets for your energies. Go itself is a stronger language because we have at least four implementations of the specification. This helps keep the compiler writers honest and avoids the language being defined by default by its most popular implementation.

Evaluation order oddity

At Canonical we’re increasingly invested in gccgo. While testing various packages built with gccgo we ran across test failures which we traced to an innocent looking piece of code.

package main

import "fmt"

type T struct {
        i int
}

func (t *T) readInt32() int32 {
        t.i += 4
        return 42 // not important
}

func main() {
        var d = T{i:200}
        end := d.i - 4 + int(d.readInt32())
        fmt.Println(end)
}

So, knowing that the Go spec defines the order of evaluation of functions calls and assignments as left to right, let’s try to predict what this code will print.

200 - 4 + 42 = 238

So, is 238 the correct answer ?

% go run odd.go 
242

Wow, that is odd. Let’s see what gccgo thinks the answer is

% go run -compiler gccgo odd.go 
238

Well, at least it got the right answer, so is gc at fault or are the arguments actually evaluated in the opposite direction ?

It turns out that both compilers are correct because the evaluation order of this sort of expression is not specified. In fact, in the spec, this case is called out in an example which is strongly reminiscent of the original code.

a := 1
f := func() int { a = 2; return 3 }
x := []int{a, f()}  // x may be [1, 3] or [2, 3]: evaluation order between a and f() is not specified

The correct solution to this problem is to break the expression into two lines, removing the ambiguity about when the addition to d.i is visible.

func main() {
        var d = T{i:200}
        v := int(d.readInt32())
        end := v + d.i - 4
        fmt.Println(end) 	// prints 242
}

More simple test coverage in Go 1.2

In a previous post I blogged about the cover tool coming in Go 1.2 and a bash helper function I use to make the tool a little easier to use.

Since then I’ve extended these helpers so I wanted to blog about the improvements.

Passing arguments to the testing tool

cover () {
  t=$(tempfile)
  go test $COVERFLAGS -coverprofile=$t $@ && go tool cover -func=$t && unlink $t
}

The first improvement is to be able to pass arguments to go test, this is done by setting COVERFLAGS before invoking the cover helper.

As an example, I have defined a flag in the sftp package tests that allow me to switch the integration tests on and off.

% cover github.com/pkg/sftp
PASS
coverage: 20.4% of statements
...
 % COVERFLAGS=-integration cover github.com/pkg/sftp 
PASS
coverage: 69.2% of statements
...

Viewing coverage details

The cover in its default mode will give you a percentage coverage on a per function basis, but it doesn’t tell you which parts of the function are uncovered.

cover-web() {
  t=$(tempfile)
  go test $COVERFLAGS -coverprofile=$t $@ && go tool cover -html=$t && unlink $t
}

To explore the coverage report in detail, this helper runs the cover tool then opens a web browser with a html version of the coverage report.

Screenshot from 2013-11-14 15:50:59Enjoy!

Stupid Go declaration tricks

This is a brief post highlighting a curious aspect of the declaration syntax in Go.

Most Go programmers know that the following of import declarations are equivalent

import "fmt"
import "math/big"

// same as
import (
        "fmt"
        "math/big"
)

The same applies to const declarations

const FORTYTWO = 42
const TRUE = 1

// same as
const (
        FORTYTWO = 42
        TRUE     = 1
)

But perhaps you didn’t know that the syntax is also valid for type declarations. For example, the following is valid syntax in Go.

type (
        B struct{ a, b int }
        C interface {
                Hello() error
        }
)

However because the func declaration has been extended to place methods on types, the following is not valid syntax

func (
        main() {
                fmt.Println("wowzers")
        }
)