Monthly Archives: September 2012

Mikio Hara’s ipv4 package

Yesterday Mikio Hara committed a new package for ipv4 handling to the go.net repository. I wanted to recognise Mikio’s work for two reasons.

  1. The level of detail and control this package offers is, in my opinion, unmatched by any other language. If you’re using C or C++, then you have the raw power of setsockopt(2) and ioctl(2) available, but you also have no guide or safety rail when using them. Mikio’s package provides exquisite control over ipv4 minutia without sacrificing the safety that Go provides.
  2. The package is a fantastic example of using conditional compilation and embedding to build a very low level package that works across all the supported Go platforms. This package compiles cleanly on Linux, *BSD, OS X and Windows without resorting to the lowest common denominator or using a single ifdef. If you are looking for examples on how to structure your code using build tags, or looking for ways to work within the Go1 API, you should study this package.

Check it out for yourselves, go.pkgdoc.org/code.google.com/p/go.net/ipv4.

Installing Go on the Raspberry Pi

Introduction

The Raspberry Pi has captured the imagination of hackers and makers alike. While it certainly wasn’t the first ARM development board on the market, its bargin basement price tag and the charitable philosophy of its inventors has sparked a huge interest in this little ARM system. What could be more appropriate for a new generation of programmers than a modern, safe and efficient programming language for their projects, Google Go.

This post describes the steps for installing Google Go from source on the Raspberry Pi. At the time of this post, trunk contains many improvements for ARM processors, including full support for cgo, which are not available in Go 1.0.x. It is expected that these enhancements will be available when Go 1.1 ships next year. If you are reading this post in September 2013, then it’s likely you will want to use the version of Go shipping with your operating system distribution rather than these instructions.

Update May, 2013 If you want to save yourself some time, precompiled binary releases of Go 1.1 for linux/arm are available. Please see the Unofficial ARM tarballs link at the top of the page.

Setting up your Pi

Before you compile Go on your Pi you should follow these steps to ensure a successful compilation. Briefly summarised, they are:

  1. Install Raspbian
  2. Configure your memory split
  3. Add some swap

Install Raspbian

The downloads page on the Raspberry Pi website contains links to SD card images for various Linux distributions. This tutorial recommends the Raspbian wheezy flavour of Debian. Follow the instructions for creating an SD card image and continue to the next step once you have ssh’d into your Raspbian installation.

Configure your memory split

The Pi comes with 256mb of memory which is shared between the video subsystem and the main processor. Compiling and linking Go programs can consume over 100mb of ram so it is recommended that the memory split be adjusted in favor of the main processor, at least while working with Go code. The Raspbian distribution makes this very easy with the raspi-config utility

% sudo raspi-config


Then reboot your system

% sudo shutdown -r now

Add some swap

To run the full test suite you will need some swap. This can be accomplished a variety of ways, using an external USB hard drive, or swapping over NFS. I’ll describe how to setup a NFS swap partition as this is the configuration I am using to generate this tutorial.

% sudo dd if=/dev/zero of=/import/nas/swap bs=1024 count=1048576
1048576+0 records in
1048576+0 records out
1073741824 bytes (1.1 GB) copied, 136.045 s, 7.9 MB/s
% sudo losetup /dev/loop0 /import/nas/swap
% sudo mkswap /dev/loop0
Setting up swapspace version 1, size = 1048572 KiB
no label, UUID=7ba9443d-c64c-416f-9931-39e3e2decf0f
% sudo swapon /dev/loop0
% free -m
             total used free shared buffers cached
Mem:           232   78  153      0       0     24
-/+ buffers/cache:   52  179
Swap:         1123   15 1108

Installing the prerequisites

Raspbian comes with almost all the tools you need to compile Go already installed, but to be sure you should install the following packages, described on the golang.org website.

% sudo apt-get install -y mercurial gcc libc6-dev

Cloning the source

% hg clone -u default https://code.google.com/p/go $HOME/go
warning: code.google.com certificate with fingerprint 9f:af:b9:ce:b5:10:97:c0:5d:16:90:11:63:78:fa:2f:37:f4:96:79 not verified (check hostfingerprints or web.cacerts config setting)
destination directory: go
requesting all changes
adding changesets
adding manifests
adding file changes
added 14430 changesets with 52478 changes to 7406 files (+5 heads)
updating to branch default
3520 files updated, 0 files merged, 0 files removed, 0 files unresolved

Building Go

% cd $HOME/go/src
% ./all.bash

If all goes well, after about 90 minutes you should see

ALL TESTS PASSED

---
Installed Go for linux/arm in /home/dfc/go
Installed commands in /home/dfc/go/bin

If there was an error relating to out of memory, or you couldn’t configure an appropriate swap device, you can skip the test suite by executing

% cd $HOME/go
% ./make.bash

as an alternative to ./all.bash.

Adding the go command to your path

The go command should be added to your $PATH

% export PATH=$PATH:$HOME/go/bin
% go version
go version devel +cfbcf8176d26 Tue Sep 25 17:06:39 2012 +1000

Now, Go and make something awesome.

Additional resources

An introduction to cross compilation with Go

Hello. Thanks for reading this article. Now that Go 1.1 has been released an updated version of this article is available.

Whoa there! This article is out of date. The release of Go 1.5 has invalidated everything below and you really should read this article instead.

Introduction

Go provides excellent support for producing binaries for foreign platforms without having to install Go on the target. This is extremely handy for testing packages that use build tags or where the target platform is not suitable for development.

Support for building a version of Go suitable for cross compilation is built into the Go build scripts; just set the GOOS, GOARCH, CGO_ENABLED and possibly GOARM correctly and invoke ./make.bash in go/src. Therefore, what follows is provided simply for convenience.

Getting started

1. Install Go from source. The instructions are well documented on the Go website, golang.org/doc/install/source. A summary for those familiar with the process follows.

% hg clone https://code.google.com/p/go
% cd go/src
% ./all.bash

2. Checkout the support scripts from Github, github.com/davecheney/golang-crosscompile

% git clone git://github.com/davecheney/golang-crosscompile.git
% source golang-crosscompile/crosscompile.bash

3. Build Go for all supported platforms

% go-crosscompile-build-all
go-crosscompile-build darwin/386
go-crosscompile-build darwin/amd64
go-crosscompile-build freebsd/386
go-crosscompile-build freebsd/amd64
go-crosscompile-build linux/386
go-crosscompile-build linux/amd64
go-crosscompile-build linux/arm
go-crosscompile-build windows/386
go-crosscompile-build windows/amd64

This will compile the Go runtime and standard library for each platform. You can see these packages if you look in $(go env GOROOT)/pkg.

% ls -1 $(go env GOROOT)/pkg 
darwin_386
darwin_amd64
freebsd_386
freebsd_amd64
linux_386
linux_amd64
linux_arm
obj
tool
windows_386
windows_amd64

Using your cross compilation environment

Sourcing crosscompile.bash provides a go-$GOOS-$GOARCH function for each platform, you can use these as you would the standard go tool. For example, to compile a program to run on linux/arm.

% cd $GOPATH/github.com/davecheney/gmx/gmxc
% go-linux-arm build 
% file ./gmxc 
./gmxc: ELF 32-bit LSB executable, ARM, version 1 (SYSV), 
statically linked, not stripped

This file is not executable on the host system (darwin/amd64), but will work on linux/arm.

Some caveats

Cross compiled binaries, not a cross compiled Go installation

This post describes how to produce an environment that will build Go programs for your target environment, it will not however build a Go environment for your target. For that, you must build Go directly on the target platform. For most platforms this means installing from source, or using a version of Go provided by your operating systems packaging system.

No cgo in cross platform builds

It is currently not possible to produce a cgo enabled binary when cross compiling from one operating system to another. This is because packages that use cgo invoke the C compiler directly as part of the build process to compile their C code and produce the C to Go trampoline functions. At the moment the name of the C compiler is hard coded to gcc, which assumes the system default gcc compiler even if a cross compiler is installed.

GOARM flag needed for cross compiling to linux/arm.

Because some arm platforms lack a hardware floating point unit the GOARM value is used to tell the linker to use hardware or software floating point code. Depending on the specifics of the target machine you are building for, you may need to supply this environment value when building.

% GOARM=5 go-linux-arm build

As of e4b20018f797 you will at least get a nice error telling you which GOARM value to use.

$ ./gmxc 
runtime: this CPU has no floating point hardware, so it cannot 
run this GOARM=7 binary. Recompile using GOARM=5.

By default, Go assumes a hardware floating point unit if no GOARM value is supplied. You can read more about Go on linux/arm on the Go Language Community Wiki.

Another go at the Next Big Language

Several weeks ago Steven Degutis posted the slides (1, 2) from his excellent presentation, The quest for the perfect programming language. In reading his slides I was reminded of a blog post made back in 2007 by Steve Yegge called The Next Big Language.

2007 was a different time for languages. While Java held the popular crown, the mainstream programming community were still coming to terms with Java 6. Released 3 months earlier, it was very much an evolution of the Java 5 watershed. Its arrival heralded the end of life for Java 1.4 and represented an opportunity to draw a line in the sand for a Java that assumed Generics and Annotation Processing. In turn this created an opening for alternate JVM languages like Groovy, JRuby and Scala, raising the discussion to a din and giving developers pause to consider a wider field of alternatives.

At the time, Yegge left me with the impression that D was his pick for the Next Big Language, although he suggested that the Next Big Language was not amongst the set on the market at that time. This fit my world view as I had just discovered D and felt  chuffed to be on the inside track of this up and coming language. D had everything that opened and shut; template metaprogramming, fast compilation, function literals, C like syntax and a memory model that someone coming from Java could grok. Two years later however, D was still stuck in 2007. This was in part due to the infighting between the standard library camps who had failed to learn from the mistakes of the Java class library and were busily adding bloat and verbosity to Phobos and Tango. Similarly those who wanted to hack on the language were bifurcated by the closed source DMD compiler and the slow moving gdc frontend. D may have been an excellent choice for those who wanted a better C++, but it wasn’t clear if actually was a market for a better C++.

At this same point in 2007, Rob Pike and Robert Griesemer were sitting, probably not far away from my office at the time, thinking the same thing. It took two years, and the addition of stalwarts like Ken Thompson, Russ Cox and Ian Lance Taylor for their creation to reach fruition; and several more years for their new language to gain mainstream awareness.

Therefore, with the benefit of hindsight that history provides, I would like to revisit the major points of Yegge’s Next Big Language, and address them in the context of Go.

Update: Go is licenced under a BSD like licence, not the MIT licence. Thanks to the astute readers on HN for noticing my mistake.

Update 2: The names of the D standard libraries are Phobos and Tango. I have also updated the list in rule 5 to be a table at the request by request.


The NBL does not replace C++, the NBL is garbage collected.

As Yegge said at the time, there will always be a bunch of engineers who think that’s evil, and they’ll continue to use C++. I think the experiences of  D have borne that out, but more importantly there is a lesson to be learnt that there is no one single language that is appropriate for all tasks. Go, as a general purpose language, is a mixture of decisions and tradeoffs that place it in the best position to reach and be relevant to mainstream developers. The choice of a garbage collected runtime was obvious for a language that held concurrency as one of its core tenets.

The NBL will have corporate backing

Looking at the origins of Java, Python, C++, Scala, with the notable exception of Ruby, Go follows the trend of having a strong corporate or academic benefactor. Google are generous and passionate supporters of Go, and while the Authors work for Google, there are many external contributors who have made substantial ongoing contributions to the language. Just as importantly, the entire project is BSD licensed (something which D was not able to do, and suffered for it) and driven by passionate, opinionated leaders. To my mind, this is the best of both worlds.

Rule #1: C-like syntax

I think of this as a courtesy to people who already have an investment in an existing mainstream language. The syntax of Go is spartan, and takes little opportunity to further this area of language design, instead leaving that to Scala or Haskell. Go’s most powerful claims in this area would be the adoption of the go fmt source code formatting tool and the elision of semicolons, both of which have a subtle, but profound impact.

Rule #2: Dynamic typing with optional static types

Go answers Yegge’s call by providing a static language with dynamic typing features through the pervasive use of interfaces and automatic type deduction.

Rule #3: Performance. The NBL will perform about as well as Java

For workloads which have at least some IO component, Go is as fast as Java or C++. It produces efficient, statically compiled programs that can be deployed trivially without the overhead of  a large runtime framework. Go programs perform as fast on their first cycle as their last, without the need for witchcraft often associated with languages targeting a JITed interpretor. While it may not be possible, because of Go’s more conservative approach to pointer arithmetic and memory safety, to best the raw computational speed of C, performance is a core design goal of the language and will continue to improve over time. Even now, I have no hesitation in recommending Go to displace any programming task which would previously have been targeted towards Java.

Rule #4: Tools

By comparison with Eclipse or Visual Studio, the automated tools available to Go programmers are limited. Taking the age of the language into account, this is to be expected. Interestingly for authors of Go programs, the experience is more akin to their dynamic cousins like Python and Ruby, who bucked the trend years before by adopting simple programming environments that offered little more than syntax highlighting.

Rule #5: Kitchen Sink

I’ll move quickly through Yegges list of must have features as their discussion would span several posts alone.

Object-literal syntax for arrays and hashes Yes
Array slicing and other intelligent collection operators Yes
Perl 5 compatible regular expression literals No
Destructuring bind (e.g. x, y = returnTwoValues()) Yes
Function literals and first-class, non-broken closures Yes
Standard OOP with classes, instances, interfaces, polymorphism, etc. No
Visibility quantifiers (public/private/protected) Yes
Iterators and generators No
List comprehensions No
Namespaces and packages Yes
Cross-platform GUI No
Operator overloading No
Keyword and rest parameters Yes
First-class parser and AST support Yes
Static typing and duck typing Yes
Type expressions and statically checkable semantics Yes
Solid string and collection libraries Yes
Strings and streams act like collections No

The final tally is 11 affirmative, 7 negative, but with the addition of items from the next paragraph, specifically threading  and continuations, I believe Go answers many of the import must haves for a mainstream language entrant. While languages like Julia or Rust approach 100% coverage of Yegge’s laundry list, it is still to be seen if they will achieve mainstream adoption.

Rule #6: Multi-Platform

Go provides outstanding cross operating system and cross architectural support. Rather than adopt Java’s lowest common denominator approach, Go allows both an escape hatch to access features specific to one platform, and a simple file name based conditional compilation system to provide platform specific implementations without having to resort to interfaces.


Rereading Yegge’s essay five years after it was published, it is clear to me that even, as Yegge claimed, he had no knowledge of the ruminations of his colleagues, the stage was set for the Next Big Language.

I believe that Go is a strong contender for the Next Big Language and I urge you to give it serious consideration.