Contents

Getting Started

What a stupid name. Unbelievable. Makes C and even Cpp/C# look like inspired branding. Search for "golang" pretty much always.

To install on Ubuntu and friends: sudo apt-get install golang-go

Note
The Ubuntu version could be quite old. Mine was 18 months old and missing important features.

Here is a very nice online tutorial which is very helpful for getting started.

To just play around with the language almost interactively you can use a very nice on-line Go compiler/executer.

Here is a beautiful idea involving whitespace. Best of luck to them.

Here is a programming framework for robots and physical things. This looks pretty neat and perhaps useful for vision applications.

Essentials

/* Old school C comment styling works. */
// And so does C++ comment styling.

package main  // Every file needs a "package" name. Maybe.
import "fmt"  // To print, the "fmt" package is needed.
/* import ("os";"math") // This works too. */

var x = 3     // Variables can be declared outside functions. Global?

func main() {
    x++ // Postfix only
    fmt.Printf("%d\n",x)  // Much like C's printf.
}

Semi-colons do not seem necessary. I think that semi-colons are generally quietly replaced by the lexer with new lines.

Seems like double quotes are quotes and apostrophes can’t be used interchangeably as in Python.

Reserved Words

Hard to find a definitive list.

src/pkg/go/token/token.go

& | ^ << >> &^ += -= *= /= %=  &= |= ^= <<= >>= &^ && || <- ++ -- == <
> = ! != <= >= := ... break case chan const continue default defer
else fallthrough for func go goto if import interface map package
range return select struct switch type var

From go.vim

byte float float32 float32 float64 float64 int int16 int32 int64 int8 uint
uint16 uint32 uint64 uint8
break cap case chan close closed const contained continue default
defer else fallthrough false for func go goto if import uintptr
interface iota len make map map new nil package panic Panicln print
println range return select string struct switch true type var

Composing and Compiling

I was pretty annoyed that syntax highlighting was not ready to go out of the box, but something like this pretty well cured it:

wget -O ~/.vim/syntax/go.vim 'http://www.vim.org/scripts/download_script.php?src_id=11735'
echo 'au BufRead,BufNewFile *.go setfiletype go' >> ~/.vimrc

The general way to compile a Go program is:

$ go build myprogram.go

The go executable has a lot of fancy things it can do helping or replacing make.

build       compile packages and dependencies
clean       remove object files
doc         run godoc on package sources
env         print Go environment information
fix         run go tool fix on packages
fmt         run gofmt on package sources
get         download and install packages and dependencies
install     compile and install packages and dependencies
list        list packages
run         compile and run Go program
test        test packages
tool        run specified go tool
version     print Go version
vet         run go tool vet on packages

Binary Size - Yikes!

At this time (2014) the Go compiler creates whopping huge files even for very trivial "hello world" kinds of programs.

$ ls -l hello* ; cat hello.go
-rwxr-xr-x 1 xed xed 1267721 Jan 21 17:04 hello
-rw-r--r-- 1 xed xed      71 Jan 21 17:04 hello.go
package main
import "fmt"
func main() { fmt.Printf("hello, world\n") }

There are a couple of reasons for this. First this binary is static. I think C programs compiled statically would also be frighteningly large if not quite this big. Also Go needs to include a complete garbage collector, concurrency management, and all its other fancy stuff. Compare the executable size to a small Python script and Python itself, for example. There is some work being done to address this issue. Hopefully this will be an area of improvement. There is also something called UPX which can make executable binaries into self-extracting compressed binaries. Apparently Go binaries don’t quite work, but again, that is being worked on. I got about a 1:4 reduction using bzip2 so there probably is a solution.

Comments

Go has many fancy core utilities that do helpful things. One is godoc which produces some kind of documentation about packages. Although optional, to get this to all work you need to make your package comments fit a particular format.

/*
  The example package provides a library for
  discussing examples. I'm just making this up of course.
  In this example, godoc will do the formatting.
  Don't do anything fancy like ******** or rely on fixed
  width ascii art, etc. Best to use complete sentences
  and assume you're writing a guide. Any comment preceding
  a top level declaration serves as a doc comment. Every
  exported (capitalized) name should have one.
*/

// Example function does some great stuff while serving
// as an example. Note how this doc comment starts with
// the function name (Example). This is apparently good
// practice.
func Example(some string) int {

Variables And Types

If a variable starts with a capital letter, then it is visible to clients of the package.

var Visible string
var _NotVisible string
var notvisible string

This means that if you’re dealing with a lower case variable, it will not be confused for something from another package. So in Python, you can define pi=3.141 and then somewhere have from math import pi and there will be confusion. Go does not ever have this problem.

Types

bool

true or false are the keywords of interest.

byte

alias for uint8

complex{64,128}
error

(Is this a type?)

float{32,64}
int, int{8,16,32,64}
uint, uint{8,16,32,64}
string

See import "strings".

var i int
var hi,low int
var red,black int = 1,2
var heads = false
var first,last = "Bert", "Russell"
var u uint = uint(hi) // Casting works on some things.

You can make your own type with the type declaration.

type Coin bool

There is also a concept of an "interface" type which is basically a named collection of methods. This type can hold any value that implements all of the methods. This is to provide the same kind of features that object oriented languages have (I think).

Short Declaration Assignment

For some reason Go uses make's := (non recursive) assignment syntax for making implicitly typed assignments within function blocks.

package main
import "fmt"

const alwayson = true   // No type needed/allowed.
var outside bool = true // Must use `var` keyword.

func main() {
    inside := 1         // Type not needed.
}

for Loop

The for statement is pretty much like C’s. When contrasting C syntax, seems like a common Go theme is to not require the parentheses (of an if or for statement) but to require the braces.

The for keyword does everything a "while" statement would do (so there is not one of those). If you leave out the setup completely for {runs_forever}, then the loop runs forever.

// for a,b,c { looped_clause }
// a. Initial condition
// b. Do the loop if true
// c. Do this every iteration. Strangely redundant with looped_clause.
for i := 0; i < 10; i++ {
    sum += i
}
x := 0
for x<100 {        // Go's "while" syntax. (No semicolons.)
   x++
   fmt.Println(x)
}

There is a special version of the for loop which uses the range keyword.

package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow { fmt.Printf("2**%d = %d\n", i, v) }
for _, v := range pow { fmt.Printf("%d\n", v) } // Skip index with _.
}  // Value can also be skipped with _.

if Conditional

b:= true
if b {                  // Or: if b == true
    fmt.Println("Yes!")
}
if b = !b; b {   // 1. Assignment (setup, like `for`); 2. Condition
    fmt.Println("No.")
} else {
    fmt.Println("Yes.")
}

Structs

Somewhat like C structs. Access components using a dot.

package main
import "fmt"

type Customer struct {
    first_name string
    last_name string
}

func main() {
    C:= Customer{"Frank","Ramsey"}
    fmt.Printf("Dear %s,", C.first_name)
}

Struct values can be omitted; they then default to zero. Not sure if that mechanism works for strings and bools and what they’d default to.

package main
import "fmt"

type Car struct {
    cc float32      // Defaults to 0
    fwd bool        // Defaults to false
    name string     // Defaults to empty string
}

func main() {
    ferrari:= Car{name:"F150"}   // Can fill in some fields or none.
    fmt.Println(ferrari)
}

Pointers

Another feature similar but different to C is the use of pointers.

  • Memory is automatically garbage collected.

  • There is no pointer arithmetic.

  • Use the address operator & to make a pointer.

  • Use the dereference operator * to turn an address back into a thing.

  • Pointers to structs can use dot notation for components just like full structs.

n:=44
fmt.Println(&n) // Produces address thing (like `0x10500188`).
nova:= new(int) // Makes a new int sized pointer, zeroed.
var nova *int = new(int) // Same as above.

Arrays

Declare an array of integers and load it up:

var pow= []int{1,2,4,8,16,32,64,128}
var xyz [3]float32
xyz[0], xyz[1], xyz[2] =  -2.2, 3.2, 0
   // Or...
xyz := []float32{-2.2,3.2,0}

Slices

Arrays support slices which are pretty similar to Python’s.

myarr[lo:hi+1] // lo starts at 0; hi is specified +1 so for 2, say 3 {0 1 2 3}
myarr[same:same] // Empty slice.
myarr[lo:lo+1] // Single element

However, some fancy Python stuff is a little weirder than it is in Python. (Of course as a Python programmer, I’m biased.) For example, slices with zero values can be == to nil, a reserved word. See this tutorial page.

Maps

A little wacky, but not even close to STL wacky.

This makes an empty, but fillable map.

package main
import "fmt"
var m map[string]int        // This just says what it is - no allocation.
func main() {
    m= make(map[string]int) // Allocation needed to prevent runtime errors...
    m["Three"] = 3          // ...when filling the empty map.
    fmt.Println(m["Three"])
}

Syntax for using map literals to initialize a map:

zip := map[string]int{
    "san diego": 92111,
    "boston"   : 02134,
    "fly creek": 13337,
}
m_t = map[string]int{}   // To initialize an empty map.

Maps support all the good stuff:

  • m[key] = val Assignment or change value.

  • x= m[key] Retrieval.

  • delete(m,key) Remove item.

  • x,ok= m[key] Here ok is either true or false depending on key’s presence.

Use range to iterate over the contents of a map:

for key, value := range m {
    fmt.Println("Key:", key, "Value:", value)
}

Here’s an official example:

Functions

Functions are generally defined with

  • Keyword func (required)

  • "Method receiver" argument list in paren (optional)

  • Function name (required)

  • Function parameter list in paren (optional)

  • Return type (not sure if required)

The "method receiver" is a way to bind the function to a user defined type. This allows you to call this function on variables of that type using a kind of object oriented syntax. The user defined type is usually a struct which allows for very oo behavior, but it can be anything you define. For example:

Method Receiver
type Coin bool

func (this Coin) Obverse() Coin {
   return !this   // I chose the name `this`. There is no `this` keyword.
}

func main() {
    var p Coin
    p = false
    fmt.Println(p.Obverse())
}

Note that the method receiver can also be a pointer to one of the package defined types. This can make it more efficient to pass objects to the method. Also, it’s important to use pointers if you want your object to be mutated. If your object will just be used in the method but not change, then you can send in a direct value. If the object needs to be changed, then use a pointer. See this example for details.

Functions can be values too (because this language is pretty sane).

package main
import "fmt"

func main() {
    p := func(s string) {fmt.Println(s)}

    p("A much less annoying print statement!")
}

There is some kind of syntax that provides for a variable number of arguments. It seems to be something like this using ellipsis:

func Printf(format string, v ...interface{}) (n int, err error) {}

The function name init() is special and can be used to set up special things for a package.

Switch

Switches are similar to C. No parens and the condition expression can be preceded with a setup expression (separated by semi-colon).

switch k {
    case 44:
        fmt.Print("Forty-four")
    case 33:
        fmt.Print("Thirty-three")
    default:
        fmt.Print("No idea, mate.")
    }

Another way to use switches is to leave the condition expression empty so that it will default to true. Then have the case expression be a test. This can be like a big if/else chain.

switch {
case level < 4:
    fmt.Println("Mild.")
case level < 7:
    fmt.Println("Moderate.")
default:
    fmt.Println("Severe!")
}

Working With Files

To read files the following will work but it will read the entire file into memory:

    import io/ioutil
    somewords,read_err:= ioutil.ReadFile(FN)
    if read_err != nil {
        fmt.Println("There was an error accessing: "+FN)
        return
    }

The good thing about this method is that it works for versions as low as 1.03. If you want to read line by line, make sure you have a later Go (1.2 works) and try something like this:

    import "bufio"
    scanner:= bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        somewords:= scanner.Text()
        linewordlist := strings.Fields( string(somewords) )
    }

This reads a line of text and then makes an array of the whitespace-separated words it finds. This example also shows how to input from standard input. Note that I’m not listing all the extra imports and any other code that may actually put this to use.

Errors

An error is anything that can describe itself as an error string. The built in type error is pretty much automatically defined by something equivalent to:

type error interface {
    Error() string
}

Wikipedia says "returning a result, err pair is the standard way to handle errors".

Concurrency

Instead of coordinating a shared state among many distributed processes, Go seems to want to use "channels" to pass values around as needed. This ensure that the values are never actively shared by separate threads of execution. Instead of having a global value X that all processes mess with erratically, processes are encouraged to send values to each other. R. Cox says of good Go programming , "Do not communicate by sharing memory; share memory by communicating." This way of thinking is similar to using Unix pipes for sharing state instead of having both pipe connected programs share the exact same memory.

Importables

$ ls /usr/share/go/src/pkg/
archive bufio builtin bytes compress container crypto database debug encoding
errors expvar flag fmt go hash html image index io log math mime net os path
reflect regexp runtime sort strconv strings sync syscall testing text time
unicode unsafe

Example

Here’s my simple bin packing example in Go.

package main
import ("fmt";"math/rand";"time")

const bincount int= 250000
const binsize int= 100
const maxitem int= 70

func next_item() int {
    return (rand.Intn(maxitem))
}

func main() {
    rand.Seed( time.Now().UTC().UnixNano())
    var bins= [bincount]int {}
    for i:=0;i<bincount;i++ {bins[i]= binsize}
    var still_room bool= true
    var item int
    for still_room == true {
        item= next_item()
        for i,_ := range bins {
            if bins[i] >= item {
                bins[i] -= item
                break
            }
            if i == bincount-1 {
                still_room= false
            }
        }
    }
    sum := 0
    for _,i:=range bins{sum+=i}
    fmt.Println(sum)
}