Go is a systems programming language intended as an alternative to C++. These are some notes on Go for experienced C++ programmers. This document discusses the differences between Go and C++, and says little to nothing about the similarities.

For a more general introduction to Go, see the Go tutorial and Effective Go.

For a detailed description of the Go language, see the Go spec.

There is more documentation about go.

## Conceptual Differences

- Go does not have classes with constructors or destructors. Instead of class methods, a class inheritance hierarchy, and virtual functions, Go provides interfaces, which are discussed in more detail below. Interfaces are also used where C++ uses templates.
- Go uses garbage collection. It is not necessary (or currently possible) to explicitly release memory. The garbage collection is (intended to be) incremental and highly efficient on modern processors.
- Go supports pointers, but does not support pointer arithmetic. You cannot use a pointer variable to walk through the bytes of a string.
- Arrays in Go are first class values. When an array is used as a function parameter, the function receives a copy of the array, not a pointer to it. However, in practice functions often use slices for parameters; slices hold pointers to underlying arrays. Slices are discussed further below.
- Strings are provided by the language. They may not be changed once they have been created.
- Hash tables are provided by the language. They are called maps.
- Separate threads of execution, and communication channels between them, are provided by the language. This is discussed further below.
- Certain types (maps and channels, described further below) are passed by reference, not by value. That is, passing a map to a function does not copy the map, and if the function changes the map the change will be seen by the caller. In C++ terms, one can think of these as being reference types.
- Go does not use header files. Instead, each source file is part of a defined package. When a package defines an object (type, constant, variable, function) with a name starting with an upper case letter, that object is visible to any other file which imports that package.
- Go does not support implicit type conversion. Operations that mix different types require casts (called conversions in Go).
- Go does not support function overloading and does not support user defined operators.
- Go does not support `const` or `volatile` qualifiers.
- Go uses `nil` for invalid pointers, where C++ uses `NULL` or simply `0`.

## Syntax

The declaration syntax is reversed compared to C++. You write the name followed by the type. Unlike C++, the syntax for a type does not match the way in which the variable is used. Type declarations may be read easily from left to right.

    Go                           C++
    var v1 int;               // int v1;
    var v2 string;            // approximately const std::string v2;
    var v3 [10]int;           // int v3[10];
    var v4 []int;             // approximately int* v4;
    var v5 struct { f int };  // struct { int f; } v5;
    var v6 *int;              // int* v6;  // but no pointer arithmetic
    var v7 map[string]int;    // approximately unordered_map<string, int>* v7;
    var v8 func(a int) int;   // int (*v8)(int a);

Declarations generally take the form of a keyword followed by the name of the object being declared. The keyword is one of `var`, `func`, `const`, or `type`. Method declarations are a minor exception in that the receiver appears before the name of the object begin declared; see the discussion of interfaces.

You can also use a keyword followed by a series of declarations in parentheses.

    var (i int; m float)

When declaring a function, you must either provide a name for each parameter or not provide a name for any parameter; you can't omit some names and provide others. You may group several names with the same type:

    func f (i, j, k int);

A variable may be initialized when it is declared. When this is done, specifying the type is permitted but not required. When the type is not specified, the type of the variable is the type of the initialization expression.

    var v = *p;

See also the discussion of constants, below. If a variable is not initialized, the type must be specified. In that case it will be implicitly initialized to 0 (or nil, or whatever). There are no uninitialized variables in Go.

Within a function, a simple declaration syntax is available with `:=` .

    v1 := v2;

This is equivalent to

    var v1 = v2;

Go permits multiple assignments, which are done in parallel.

    i, j = j, i;   // Swap i and j.

Functions may have multiple return values, indicated by a list in parentheses. The returned values can be stored by assignment to a list of variables.

    func f() (i int, j int);
    v1, v2 = f();

Go treats semicolons as separators, not terminators. Moreover, a semicolon is not required after a curly brace ending a type declaration (e.g., `var s struct {}`) or a block. Semicolons are never required at the top level of a file (between global declarations). However, they are always permitted at the end of a statement, so you can continue using them as in C++.

When using a pointer to a struct, you use `.` instead of `->`. Thus syntactically speaking a structure and a pointer to a structure are used in the same way.

    type myStruct struct { i int }
    var v9 myStruct;             // v9 has structure type
    var p9 *myStruct;            // p9 is a pointer to a structure
    f(v9.i, p9.i)

Go does not require parentheses around the condition of a `if` statement, or the expressions of a `for` statement, or the value of a `switch` statement. On the other hand, it does require curly braces around the body of an `if` or `for` statement.

    if a < b { f() }          // Valid
    if (a < b) { f() }        // Valid (condition is parenthesized expression)
    if (a < b) f();           // INVALID
    for i = 0; i < 10; i++ {}    // Valid
    for (i = 0; i < 10; i++) {}  // INVALID

Go does not have a `while` statement nor does it have a `do/while` statement. The `for` statement may be used with a single condition, which makes it equivalent to a `while` statement. Omitting the condition entirely is an endless loop.

Go permits `break` and `continue` to specify a label. The label must refer to a `for`, `switch`, or `select` statement.

In a `switch` statement, `case` labels do not fall through. You can make them fall through using the `fallthrough` keyword. This applies even to adjacent cases.

    switch i { case 0: case 1: f() } // f is not called when i == 0!

But a `case` can have multiple values.

    switch i { case 0, 1: f() } // f is called if i == 0 || i == 1.

The values in a `case` need not be constants—or even integers; any type that supports the equality comparison operator, such as strings or pointers, can be used—and if the `switch` value is omitted it defaults to `true`.

    switch { case i < 0: f1() case i == 0: f2() case i > 0: f3() }

The `++` and `--` operators may only be used in statements, not in expressions. You cannot write `c = *p++`. `*p++` is parsed as `(*p)++`.

The `defer` statement may be used to call a function after the function containing the `defer` statement returns.

    fd := open("filename");
    defer close(fd);        // fd will be closed when this function returns.

## Constants

In Go constants may be untyped. This applies even to constants named with a `const` declaration if no type is given in the declaration and the initializer expression uses only untyped constants. A value derived from an untyped constant becomes typed when it is used within a context that requires a typed value. This permits constants to be used relatively freely without requiring general implicit type conversion.

    var a uint; f(a + 1)  // untyped numeric constant "1" becomes typed as uint

The language does not impose any limits on the size of an untyped numeric constant or constant expression. A limit is only applied when a constant is used where a type is required.

    const huge = 1 << 100; f(huge >> 98)

Go does not support enums. Instead, you can use the special name `iota` in a single `const` declaration to get a series of increasing value. When an initialization expression is omitted for a `const`, it reuses the preceding expression.

    const ( red = iota; blue; green ) // red == 0, blue == 1, green == 2

## Slices

A slice is conceptually a struct with three fields: a pointer to an array, a length, and a capacity. Slices support the `[]` operator to access elements of the underlying array. The builtin `len` function returns the length of the slice. The builtin `cap` function returns the capacity.

Given an array, or another slice, a new slice is created via `a[I:J]`. This creates a new slice which refers to `a`, starts at index `I`, and ends at index `J - 1`. It has length `J - I`. The new slice refers to the same array to which `a` refers. That is, changes made using the new slice may be seen using `a`. The capacity of the new slice is simply the capacity of `a` minus `I`. The capacity of an array is the length of the array. You may also assign a pointer to an array to a variable of slice type; given `var s []int; var a[10] int`, `s = &a` is more or less the same as `s = a[0:len(a)]`.

What this means is that Go uses slices for some cases where C++ uses pointers. If you create a value of type `[100]byte` (an array of 100 bytes, perhaps a buffer) and you want to pass it to a function without copying it, you should declare the function parameter to have type `[]byte`, and pass the address of the array. Unlike C++, it is not necessary to pass the length of the buffer; it is efficiently accessible via `len`.

The slice syntax may also be used with a string. It returns a new string, whose value is a substring of the original string. Because strings are immutable, string slices can be implemented without allocating new storage for the slices's contents.

## Making values

Go has a builtin function `new` which takes a type and allocates space on the heap. The allocated space will be zero-initialized for the type. For example, `new(int)` allocates a new int on the heap, initializes it with the value `0`, and returns its address, which has type `*int`. Unlike in C++, `new` is a function, not an operator; `new int` is a syntax error.

Map and channel values must be allocated using the builtin function `make`. A variable declared with map or channel type without an initializer will be automatically initialized to `nil`. Calling `make(map[int]int)` returns a newly allocated value of type `map[int]int`. Note that `make` returns a value, not a pointer. This is consistent with the fact that map and channel values are passed by reference. Calling `make` with a map type takes an optional argument which is the expected capacity of the map. Calling `make` with a channel type takes an optional argument which sets the buffering capacity of the channel; the default is 0 (unbuffered).

The `make` function may also be used to allocate a slice. In this case it allocates memory for the underlying array and returns a slice referring to it. There is one required argument, which is the number of elements in the slice. A second, optional, argument is the capacity of the slice. For example, `make([]int, 10, 20)`. This is identical to `new([20]int)[0:10]`. Since Go uses garbage collection, the newly allocated array will be discarded sometime after there are no references to the returned slice.

## Interfaces

Where C++ provides classes, subclasses and templates, Go provides interfaces. A Go interface is similar to a C++ pure abstract class: a class with no data members, with methods which are all pure virtual. However, in Go, any type which provides the methods named in the interface may be treated as an implementation of the interface. No explicitly declared inheritance is required. The implementation of the interface is entirely separate from the interface itself.

A method looks like an ordinary function definition, except that it has a receiver. The receiver is similar to the `this` pointer in a C++ class method.

    type myType struct { i int }
    func (p *myType) get() int { return p.i }

This declares a method `get` associated with `myType`. The receiver is named `p` in the body of the function.

Methods are defined on named types. If you convert the value to a different type, the new value will have the methods of the new type, not the old type.

You may define methods on a builtin type by declaring a new named type derived from it. The new type is distinct from the builtin type.

    type myInteger int
    func (p myInteger) get() int { return int(p) } // Conversion required.
    func f(i int) { }
    var v myInteger
    // f(v) is invalid.
    // f(int(v)) is valid; int(v) has no defined methods.

Given this interface:

    type myInterface interface {
    	get() int;
    	set(i int);
    }

we can make `myType` satisfy the interface by additionally writing

    func (p *myType) set(i int) { p.i = i }

Now any function which takes `myInterface` as a parameter will accept a variable of type `*myType`.

    func getAndSet(x myInterface) {}
    func f1() {
    	var p myType;
    	getAndSet(&p);
    }

In other words, if we view `myInterface` as a C++ pure abstract base class, defining `set` and `get` for `*myType` made `*myType` automatically inherit from `myInterface`. A type may satisfy multiple interfaces.

An anonymous field may be used to implement something much like a C++ child class.

    type myChildType struct { myType; j int }
    func (p *myChildType) get() int { p.j++; return (&p.myType).get() }

This effectively implements `myChildType` as a child of `myType`.

    func f2() {
    	var p myChildType;
    	getAndSet(&p)
    }

The `set` method is effectively inherited from `myChildType`, because methods associated with the anonymous type are promoted to become methods of the enclosing type. In this case, because `myChildType` has an anonymous field of type `myType`, the methods of `myType` also become methods of `myChildType`. In this example, the `get` method was overridden, and the `set` method was inherited.

This is not precisely the same as a child class in C++. When a parent method is called, it receives a pointer to the field in the child class. If the parent method calls some other method on its argument, it will call the method associated with the parent class, not the method associated with the child class. In other words, methods are not virtual functions. When you want the equivalent of a virtual function, use an interface.

A variable which has an interface type may be converted to have a different interface type using a special construct called a type assertion. This is implemented dynamically at runtime, like C++ `dynamic_cast`. Unlike `dynamic_cast`, there does not need to be any declared relationship between the two interfaces.

    type myPrintInterface interface {
      print();
    }
    func f3(x myInterface) {
    	x.(myPrintInterface).print()  // type assertion to myPrintInterface
    }

The conversion to `myPrintInterface` is entirely dynamic. It will work as long as the underlying type of x (the dynamic type) defines a `print` method.

Because the conversion is dynamic, it may be used to implement generic programming similar to templates in C++. This is done by manipulating values of the minimal interface.

    type Any interface { }

Containers may be written in terms of `Any`, but the caller must unbox using a type assertion to recover values of the contained type. As the typing is dynamic rather than static, there is no equivalent of the way that a C++ template may inline the relevant operations. The operations are fully type-checked at runtime, but all operations will involve a function call.

    type iterator interface {
    	get() Any;
    	set(v Any);
    	increment();
    	equal(arg *iterator) bool;
    }

## Goroutines

Go permits starting a new thread of execution (a goroutine) using the `go` statement. The `go` statement runs a function in a different, newly created, goroutine. All goroutines in a single program share the same address space.

Internally, goroutines act like coroutines that are multiplexed among multiple operating system threads. You do not have to worry about these details.

    func server(i int) { for { print(i); sys.sleep(10) } }
    go server(1); go server(2);

(Note that the `for` statement in the `server` function is equivalent to a C++ `while (true)` loop.)

Goroutines are (intended to be) cheap.

Function literals (which Go implements as closures) can be useful with the `go` statement.

    var g int;
    go func(i int) {
    	s := 0
    	for j := 0; j < i; j++ { s += j }
    	g = s;
    } (1000); // Passes argument 1000 to the function literal.

## Channels

Channels are used to communicate between goroutines. Any value may be sent over a channel. Channels are (intended to be) efficient and cheap. To send a value on a channel, use `<-` as a binary operator. To receive a value on a channel, use `<-` as a unary operator. When calling functions, channels are passed by reference.

The Go library provides mutexes, but you can also use a single goroutine with a shared channel. Here is an example of using a manager function to control access to a single value.

    type cmd struct { get bool; val int }
    func manager(ch chan cmd) {
    	var val int = 0;
    	for {
    		c := <- ch
    		if c.get { c.val = val; ch <- c }
    		else { val = c.val }
    	}
    }

In that example the same channel is used for input and output. This means that if two goroutines try to retrieve the value at the same time, the first goroutine may read the response which was triggered by the second goroutine's request. In simple cases that is fine. For more complex cases, pass in a channel.

    type cmd2 struct { get bool; val int; ch <- chan int; }
    func manager2(ch chan cmd2) {
    	var val int = 0;
    	for {
    		c := <- ch
    		if c.get { c.ch <- val }
    		else { val = c.val }
    	}
    }

To use `manager2`, given a channel to it:

    func f4(ch <- chan cmd2) int {
    	myCh := make(chan int);
    	c := cmd2{ true, 0, myCh };  // Composite literal syntax.
    	ch <- c;
    	return <- myCh;
    }