<!-- Go For C++ Programmers -->
<p>
-Go is a systems programming language intended as an alternative to C++.
+Go is a systems programming language intended to be a general-purpose
+systems language, like 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 detailed description of the Go language, see the
<a href="go_spec.html">Go spec</a>.
-<p>
-There is more <a href="/">documentation about go</a>.
-
<h2 id="Conceptual_Differences">Conceptual Differences</h2>
<ul>
<a href="#Interfaces">discussed in more detail below</a>.
Interfaces are also used where C++ uses templates.
-<li>Go uses garbage collection. It is not necessary (or currently possible)
- to explicitly release memory. The garbage collection is (intended to be)
+<li>Go uses garbage collection. It is not necessary (or possible)
+ to release memory explicitly. The garbage collection is (intended to be)
incremental and highly efficient on modern processors.
-<li>Go supports pointers, but does not support pointer arithmetic. You cannot
+<li>Go has pointers but not pointer arithmetic. You cannot
use a pointer variable to walk through the bytes of a string.
<li>Arrays in Go are first class values. When an array is used as a
<p>
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
+followed by the type. Unlike in 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.
<pre>
<b>Go C++</b>
var v1 int; // int v1;
-var v2 string; // approximately const std::string v2;
+var v2 string; // const std::string v2; (approximately)
var v3 [10]int; // int v3[10];
-var v4 []int; // approximately int* v4;
+var v4 []int; // int* v4; (approximately)
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 v6 *int; // int* v6; (but no pointer arithmetic)
+var v7 map[string]int; // unordered_map<string, int>* v7; (approximately)
var v8 func(a int) int; // int (*v8)(int a);
</pre>
<code>func</code>,
<code>const</code>, or <code>type</code>. Method declarations are a minor
exception in that
-the receiver appears before the name of the object begin declared; see
+the receiver appears before the name of the object being declared; see
the <a href="#Interfaces">discussion of interfaces</a>.
<p>
parentheses.
<pre>
-var (i int; m float)
+var (
+ i int;
+ m float
+)
</pre>
<p>
and provide others. You may group several names with the same type:
<pre>
-func f (i, j, k int);
+func f(i, j, k int, s, t string);
</pre>
<p>
<p>
See also the <a href="#Constants">discussion of constants, below</a>.
-If a variable is not initialized, the type must be specified.
+If a variable is not initialized explicitly, the type must be specified.
In that case it will be
-implicitly initialized to 0 (or nil, or whatever). There are no
+implicitly initialized to the type's zero value (0, nil, etc.). There are no
uninitialized variables in Go.
<p>
-Within a function, a simple declaration syntax is available with
+Within a function, a short declaration syntax is available with
<code>:=</code> .
<pre>
<p>
Go treats semicolons as separators, not terminators. Moreover,
-a semicolon
-is not required after a curly brace ending a type declaration (e.g.,
-<code>var s struct {}</code>) or a block. Semicolons are never required at the
+semicolons may be omitted after the closing parenthesis of a declaration
+block or after a closing brace that is not part of an expression
+(e.g., <code>var s struct {}</code> or <code>{ x++ }</code>).
+Semicolons are never required at the
top level of a file (between global declarations). However, they are
always <em>permitted</em> at
the end of a statement, so you can continue using them as in C++.
<pre>
if a < b { f() } // Valid
-if (a < b) { f() } // Valid (condition is parenthesized expression)
+if (a < b) { f() } // Valid (condition is a parenthesized expression)
if (a < b) f(); // INVALID
for i = 0; i < 10; i++ {} // Valid
for (i = 0; i < 10; i++) {} // INVALID
even to adjacent cases.
<pre>
-switch i { case 0: case 1: f() } // f is not called when i == 0!
+switch i {
+case 0: // empty case body
+case 1:
+ f() // f is not called when i == 0!
+}
</pre>
<p>
But a <code>case</code> can have multiple values.
<pre>
-switch i { case 0, 1: f() } // f is called if i == 0 || i == 1.
+switch i {
+case 0, 1:
+ f() // f is called if i == 0 || i == 1.
+}
</pre>
<p>
value is omitted it defaults to <code>true</code>.
<pre>
-switch { case i < 0: f1() case i == 0: f2() case i > 0: f3() }
+switch {
+case i < 0:
+ f1()
+case i == 0:
+ f2()
+case i > 0:
+ f3()
+}
</pre>
<p>
<p>
In Go constants may be <i>untyped</i>. This applies even to constants
-named with a <code>const</code> declaration if no
+named with a <code>const</code> 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
freely without requiring general implicit type conversion.
<pre>
-var a uint; f(a + 1) // untyped numeric constant "1" becomes typed as uint
+var a uint;
+f(a + 1) // untyped numeric constant "1" becomes typed as uint
</pre>
<p>
a constant is used where a type is required.
<pre>
-const huge = 1 << 100; f(huge >> 98)
+const huge = 1 << 100;
+f(huge >> 98)
</pre>
<p>
it reuses the preceding expression.
<pre>
-const ( red = iota; blue; green ) // red == 0, blue == 1, green == 2
+const (
+ red = iota; // red == 0
+ blue; // blue == 1
+ green // green == 2
+)
</pre>
<h2 id="Slices">Slices</h2>
Given an array, or another slice, a new slice is created via
<code>a[I:J]</code>. This
creates a new slice which refers to <code>a</code>, starts at
-index <code>I</code>, and ends at index
-<code>J - 1</code>. It has length <code>J - I</code>.
+index <code>I</code>, and ends before index
+<code>J</code>. It has length <code>J - I</code>.
The new slice refers to the same array
to which <code>a</code>
refers. That is, changes made using the new slice may be seen using
<code>a</code>. The
capacity of the new slice is simply the capacity of <code>a</code> minus
<code>I</code>. 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 <code>var s []int; var a[10] int</code>,
-<code>s = &a</code> is more or
-less the same as <code>s = a[0:len(a)]</code>.
+of an array is the length of the array. You may also assign an array pointer
+to a variable of slice type; given <code>var s []int; var a[10] int</code>,
+the assignment <code>s = &a</code> is equivalent to
+<code>s = a[0:len(a)]</code>.
<p>
What this means is that Go uses slices for some cases where C++ uses pointers.
buffer) and you want to pass it to a function without copying it, you should
declare the function parameter to have type <code>[]byte</code>, and pass the
address
-of the array. Unlike C++, it is not
+of the array. Unlike in C++, it is not
necessary to pass the length of the buffer; it is efficiently accessible via
<code>len</code>.
</pre>
<p>
-we can make <code>myType</code> satisfy the interface by additionally writing
+we can make <code>myType</code> satisfy the interface by adding
<pre>
func (p *myType) set(i int) { p.i = i }
<pre>
type myChildType struct { myType; j int }
-func (p *myChildType) get() int { p.j++; return (&p.myType).get() }
+func (p *myChildType) get() int { p.j++; return p.myType.get() }
</pre>
<p>
<p>
The <code>set</code> method is effectively inherited from
<code>myChildType</code>, because
-methods associated with the anonymous type are promoted to become methods
+methods associated with the anonymous field are promoted to become methods
of the enclosing type. In this case, because <code>myChildType</code> has an
anonymous field of type <code>myType</code>, the methods of
<code>myType</code> also become methods of <code>myChildType</code>.
overridden, and the <code>set</code> method was inherited.
<p>
-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.
+This is not precisely the same as a child class in C++.
+When a method of an anonymous field is called,
+its receiver is the field, not the surrounding struct.
+In other words, methods on anonymous fields are not virtual functions.
+When you want the equivalent of a virtual function, use an interface.
<p>
A variable which has an interface type may be converted to have a
about these details.
<pre>
-func server(i int) { for { print(i); sys.sleep(10) } }
-go server(1); go server(2);
+func server(i int) {
+ for {
+ print(i);
+ sys.sleep(10)
+ }
+}
+go server(1);
+go server(2);
</pre>
<p>
s := 0
for j := 0; j < i; j++ { s += j }
g = s;
-} (1000); // Passes argument 1000 to the function literal.
+}(1000); // Passes argument 1000 to the function literal.
</pre>
<h2 id="Channels">Channels</h2>
</pre>
<p>
-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.
+In that example the same channel is used for input and output.
+This is incorrect if there are multiple goroutines communicating
+with the manager at once: a goroutine waiting for a response
+from the manager might receive a request from another goroutine
+instead.
+A solution is to pass in a channel.
<pre>
type cmd2 struct { get bool; val int; ch <- chan int; }
myCh := make(chan int);
c := cmd2{ true, 0, myCh }; // Composite literal syntax.
ch <- c;
- return <- myCh;
+ return <-myCh;
}
</pre>