diff options
author | Russ Cox <rsc@golang.org> | 2009-11-08 01:08:26 -0800 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-11-08 01:08:26 -0800 |
commit | c91275bed12bf4e840cc6c8c0cf4400d7cadb463 (patch) | |
tree | 6c6d3b9f23822bf656fd748753f22f84d50e4a9d | |
parent | 06b3098bf79c108cf90bcf637567d323fec7f807 (diff) | |
download | golang-c91275bed12bf4e840cc6c8c0cf4400d7cadb463.tar.gz |
go for c++ programmers; fixes.
the most substantial are the wording around semicolons
and around the channel manager nits. both were subtly
incorrect.
R=iant, r
CC=go-dev
http://go/go-review/1025018
-rw-r--r-- | doc/go_for_cpp_programmers.html | 137 |
1 files changed, 82 insertions, 55 deletions
diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html index b6990c362..9920e016b 100644 --- a/doc/go_for_cpp_programmers.html +++ b/doc/go_for_cpp_programmers.html @@ -1,7 +1,8 @@ <!-- 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. @@ -15,9 +16,6 @@ For a more general introduction to Go, see the 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> @@ -27,11 +25,11 @@ There is more <a href="/">documentation about go</a>. <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 @@ -77,19 +75,19 @@ There is more <a href="/">documentation about go</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> @@ -99,7 +97,7 @@ of the object being declared. The keyword is one of <code>var</code>, <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> @@ -107,7 +105,10 @@ You can also use a keyword followed by a series of declarations in parentheses. <pre> -var (i int; m float) +var ( + i int; + m float +) </pre> <p> @@ -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: <pre> -func f (i, j, k int); +func f(i, j, k int, s, t string); </pre> <p> @@ -131,13 +132,13 @@ var v = *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> @@ -170,9 +171,10 @@ v1, v2 = f(); <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++. @@ -198,7 +200,7 @@ around the body of an <code>if</code> or <code>for</code> statement. <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 @@ -224,14 +226,21 @@ make them fall through using the <code>fallthrough</code> keyword. This applies 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> @@ -242,7 +251,14 @@ pointers, can be used—and if the <code>switch</code> 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> @@ -264,7 +280,7 @@ defer close(fd); // fd will be closed when this function returns. <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 @@ -273,7 +289,8 @@ requires a typed value. This permits constants to be used relatively 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> @@ -282,7 +299,8 @@ numeric constant or constant expression. A limit is only applied when 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> @@ -293,7 +311,11 @@ value. When an initialization expression is omitted for a <code>const</code>, 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> @@ -312,19 +334,18 @@ capacity. 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. @@ -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 <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>. @@ -437,7 +458,7 @@ type myInterface interface { </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 } @@ -469,7 +490,7 @@ class. <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> @@ -486,7 +507,7 @@ func f2() { <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>. @@ -494,12 +515,11 @@ In this example, the <code>get</code> method was 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 @@ -565,8 +585,14 @@ multiple operating system threads. You do not have to worry 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> @@ -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. </pre> <h2 id="Channels">Channels</h2> @@ -619,11 +645,12 @@ func manager(ch chan cmd) { </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; } @@ -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; } </pre> |