Blog

Small Go interfaces

I wanted to test a function that wrote a report without letting the test create files. My first instinct, trained by larger object systems, was to invent a report hierarchy. Go let me stop much earlier.

The function only needs one operation:

type writer interface {
	Write([]byte) (int, os.Error)
}

func report(w writer, name string) os.Error {
	_, err := w.Write([]byte("hello, " + name + "\n"))
	return err
}

A file can satisfy that interface. So can a network connection or a little buffer in a test. None of those types has to announce that it implements writer; the method set is enough.

That last detail was my surprise. I am used to a type naming its interfaces at the type declaration. Here the relationship can be discovered where it is needed. The package containing report can define the narrow interface, even when the concrete type belongs to another package and cannot be edited.

The mechanism is structural. An interface describes a set of methods. A value is assignable to it when its type has those methods with the right signatures. The compiler checks the assignment, so this is not hopeful late binding. Calls through the interface still carry dynamic type information, but the agreement itself needs no explicit declaration.

Pointer methods add one wrinkle. If a method has a pointer receiver, a pointer to the type has that method; the plain value does not. That distinction matters when a method modifies state, and it explains several otherwise puzzling assignment errors.

I now prefer interfaces declared by the code that consumes them, and I keep them as small as the operation permits. A one-method interface is not a toy. It is often a precise seam between a useful function and everything it does not need to know.

The caveat is that an interface should represent behaviour, not merely hide every concrete type on principle. Returning an interface too early can discard useful methods and make code harder to follow. If there is only one implementation and no boundary to protect, the concrete type is frequently clearer.

Here, one method bought a test with no temporary file and no elaborate framework. I will take that trade.

Anagramizer, a simple anagram solver in Go

This weekend I took the family to celebrate Father’s Day away from town. We went around getting to know parts of the province we live in and never been to.

We came back yesterday and the plan today was for a nice, calm day at home (it’s a holiday of some sort here.) Then I got engaged in a game called Hanging with Friends, a mix of the traditional hangman with a bit of Scrabble.

Since English isn’t my first language, I have a limited vocabulary, which leaves me at a disadvantage against my English-speaking friends. I can handle the “hangman” part of the game where I have to guess the word my friends come up with; but when it becomes “Scrabble” and I’ve got to form words using only a given set of letters and still make them difficult enough that a native English speaker will have problems figuring them out, then it’s tough.

An itch that needed some scratching. Enter Anagramizer.

When I woke up this morning, I decided to write a little program to help me. You call it cheating, I call it having a bit of nerd fun.

Being that I’m currently in love with Go, I decided to write in that language and it was really easy and quick to do it. It took me about half an hour to write the program that did what I needed. But then…

I succumbed to the temptation and started adding bells and whistles. Admittedly it was mostly for my own amusement and trying stuff in Go, but by the time we were leaving for lunch, the program had more options than the KDE audio volume utility (see what I did just there?)

I decided to make it available to anyone who wants to play with it. It served its purpose of entertaining me for about half a day 🙂

It’s now available on Github and released under a BSD licence.

Euler 9 in Go

For fun I picked one of the Euler algorithms I had played with before and rewrote it in Go. Instead of carrying over the nested-loop search, this version first eliminates c using the fixed sum and solves the Pythagorean equation for b. Only a remains to search.

package main

import (
	"fmt"
	"os"
)

func main() {
	const sum = 1000

	for a := 1; a < sum/3; a++ {
		numerator := sum * (sum - 2*a)
		denominator := 2 * (sum - a)

		if numerator%denominator != 0 {
			continue
		}

		b := numerator / denominator
		c := sum - a - b
		if a < b && b < c {
			fmt.Println(a * b * c)
			return
		}
	}

	fmt.Fprintln(os.Stderr, "no solution")
	os.Exit(1)
}

The divisibility check rejects values of a that would produce a fractional b. The program uses constant space, examines fewer than sum / 3 candidates, and prints 31875000.

How to set up Emacs on Windows

Just so I have it documented somewhere for future reference, here’s how to quickly set GNU Emacs up on Windows.

  1. Download it from http://ftp.gnu.org/gnu/emacs/windows/

  2. Unzip it to, say, C:emacs or something like that

  3. Set the environment variable HOME to C:emacs and include C:emacsbin to the PATH

  4. If you want to have a “Open with _G_NU Emacs” option on the context menu, just create a registry file (call it emacs.reg or whatever.reg) with the contents below and double-click it to import it into the registry.

REGEDIT4  
[HKEY\_CLASSES\_ROOT*shell]

[HKEY\_CLASSES\_ROOT*shellemacsmenu]  
@=&ldquo;Open with &GNU; Emacs&rdquo;

[HKEY\_CLASSES\_ROOT*shellemacsmenucommand]  
@=&ldquo;C:emacsbinrunemacs.exe &rdquo;%1&ldquo;&rdquo;

Et voilà! As well, for my preferred colour scheme, we need to use color-theme from http://www.nongnu.org/color-theme/ and set it up in your .emacs file:

(add-to-list 'load-path "c:/emacs/.emacs.d")
(require 'color-theme)
(color-theme-initialize)
(when (display-graphic-p)
  (color-theme-subtle-hacker)

Living on Go weekly snapshots

I rebuilt Go this morning because a small program stopped compiling after I pulled the latest sources. That sounds like a complaint, but it was exactly the experiment I wanted. Go is still young enough that a weekly snapshot can change a familiar corner of the language before I have finished becoming familiar with it.

The simplest way I have found to stay sane is to keep the experiment small:

package main

import "fmt"

func main() {
	fmt.Println("hello from this week's Go")
}

I build that first, then my real code. If this fails, my tree or environment is wrong. If it works and the real program does not, I have a migration to understand rather than a mysterious compiler disaster.

The surprising part is how useful the release number becomes. A report that says “tip is broken” has a shelf life measured in minutes. A report that includes the release.r57 family, the compiler, the operating system, and a reduced program gives everybody something concrete to compare. The weekly tags are not decoration; they are coordinates on moving ground.

There is a mechanical reason for the churn. The language, compilers, runtime, and libraries live together and are being designed together. A syntax adjustment can therefore arrive beside the library changes needed to use it. That is convenient for the project and occasionally inconvenient for the person who pulled five minutes before lunch.

I prefer snapshots to copying a random revision from the main repository. A named snapshot gives me a point I can return to and makes two machines easier to compare. I also keep Go code outside the source tree and rebuild from a clean checkout when results become implausible.

That record helps with library changes too. When a package function moves or changes shape, I can read the notes between two known points instead of searching the entire repository history. Small coordinates turn a broad question into a short diff.

The caveat is obvious: weekly does not mean stable. I would not quietly update a production compiler and hope for character-building surprises. For experiments, however, the snapshots make the cost of change visible while the changes are still small. My program broke, I learned why, and lunch was only slightly delayed.