diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html index b6990c3625..9920e016b0 100644 --- a/doc/go_for_cpp_programmers.html +++ b/doc/go_for_cpp_programmers.html @@ -1,7 +1,8 @@
-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. @@ -15,9 +16,6 @@ For a more general introduction to Go, see the For a detailed description of the Go language, see the Go spec. -
-There is more documentation about go. -
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.
Go C++
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);
@@ -99,7 +97,7 @@ 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 receiver appears before the name of the object being declared; see
the discussion of interfaces.
@@ -107,7 +105,10 @@ You can also use a keyword followed by a series of declarations in parentheses.
-var (i int; m float) +var ( + i int; + m float +)
@@ -116,7 +117,7 @@ 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); +func f(i, j, k int, s, t string);
@@ -131,13 +132,13 @@ var v = *p;
See also the discussion of constants, below. -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.
-Within a function, a simple declaration syntax is available with
+Within a function, a short declaration syntax is available with
:= .
@@ -170,9 +171,10 @@ 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 +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.,var s struct {}or{ x++ }). +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++. @@ -198,7 +200,7 @@ around the body of aniforforstatement.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 @@ -224,14 +226,21 @@ make them fall through using thefallthroughkeyword. This applies even to adjacent cases.-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! +}But a
casecan have multiple values.-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. +}@@ -242,7 +251,14 @@ pointers, can be used—and if the
switchvalue is omitted it defaults totrue.-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() +}@@ -264,7 +280,7 @@ defer close(fd); // fd will be closed when this function returns.
In Go constants may be untyped. This applies even to constants -named with a
constdeclaration if no +named with aconstdeclaration, 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 @@ -273,7 +289,8 @@ 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 +var a uint; +f(a + 1) // untyped numeric constant "1" becomes typed as uint@@ -282,7 +299,8 @@ 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) +const huge = 1 << 100; +f(huge >> 98)@@ -293,7 +311,11 @@ 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 +const ( + red = iota; // red == 0 + blue; // blue == 1 + green // green == 2 +)Slices
@@ -312,19 +334,18 @@ capacity. Given an array, or another slice, a new slice is created viaa[I:J]. This creates a new slice which refers toa, starts at -indexI, and ends at index -J - 1. It has lengthJ - I. +indexI, and ends before index +J. It has lengthJ - I. The new slice refers to the same array to whicharefers. That is, changes made using the new slice may be seen usinga. The capacity of the new slice is simply the capacity ofaminusI. 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; givenvar s []int; var a[10] int, -s = &ais more or -less the same ass = a[0:len(a)]. +of an array is the length of the array. You may also assign an array pointer +to a variable of slice type; givenvar s []int; var a[10] int, +the assignments = &ais equivalent to +s = a[0:len(a)].What this means is that Go uses slices for some cases where C++ uses pointers. @@ -333,7 +354,7 @@ 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 +of the array. Unlike in C++, it is not necessary to pass the length of the buffer; it is efficiently accessible vialen. @@ -437,7 +458,7 @@ type myInterface interface {-we can make
myTypesatisfy the interface by additionally writing +we can makemyTypesatisfy the interface by addingfunc (p *myType) set(i int) { p.i = i } @@ -469,7 +490,7 @@ class.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() }@@ -486,7 +507,7 @@ func f2() {
The
setmethod is effectively inherited frommyChildType, 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, becausemyChildTypehas an anonymous field of typemyType, the methods ofmyTypealso become methods ofmyChildType. @@ -494,12 +515,11 @@ In this example, thegetmethod was overridden, and thesetmethod 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. +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.
A variable which has an interface type may be converted to have a @@ -565,8 +585,14 @@ 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); +func server(i int) { + for { + print(i); + sys.sleep(10) + } +} +go server(1); +go server(2);@@ -586,7 +612,7 @@ go func(i int) { 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.
Channels
@@ -619,11 +645,12 @@ func manager(ch chan cmd) {
-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.
type cmd2 struct { get bool; val int; ch <- chan int; }
@@ -645,6 +672,6 @@ func f4(ch <- chan cmd2) int {
myCh := make(chan int);
c := cmd2{ true, 0, myCh }; // Composite literal syntax.
ch <- c;
- return <- myCh;
+ return <-myCh;
}