diff options
Diffstat (limited to 'doc/go_for_cpp_programmers.html')
-rw-r--r-- | doc/go_for_cpp_programmers.html | 707 |
1 files changed, 0 insertions, 707 deletions
diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html deleted file mode 100644 index 7168f1d05..000000000 --- a/doc/go_for_cpp_programmers.html +++ /dev/null @@ -1,707 +0,0 @@ -<!-- Go For C++ Programmers --> - -<p> -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. - -<p> -For a more general introduction to Go, see the -<a href="go_tutorial.html">Go tutorial</a> and -<a href="effective_go.html">Effective Go</a>. - -<p> -For a detailed description of the Go language, see the -<a href="go_spec.html">Go spec</a>. - -<h2 id="Conceptual_Differences">Conceptual Differences</h2> - -<ul> -<li>Go does not have classes with constructors or destructors. - Instead of class methods, a class inheritance hierarchy, - and virtual functions, Go provides <em>interfaces</em>, which are - <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 possible) - to release memory explicitly. The garbage collection is (intended to be) - incremental and highly efficient on modern processors. - -<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 - 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 <a href="#Slices">discussed further below</a>. - -<li>Strings are provided by the language. They may not be changed once they - have been created. - -<li>Hash tables are provided by the language. They are called maps. - -<li>Separate threads of execution, and communication channels between - them, are provided by the language. This - is <a href="#Goroutines">discussed further below</a>. - -<li>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. - -<li>Go does not use header files. Instead, each source file is part of a - defined <em>package</em>. 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. - -<li>Go does not support implicit type conversion. Operations that mix - different types require casts (called conversions in Go). - -<li>Go does not support function overloading and does not support user - defined operators. - -<li>Go does not support <code>const</code> or <code>volatile</code> qualifiers. - -<li>Go uses <code>nil</code> for invalid pointers, where C++ uses - <code>NULL</code> or simply <code>0</code>. -</ul> - -<h2 id="Syntax">Syntax</h2> - -<p> -The declaration syntax is reversed compared to C++. You write the name -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 // const std::string v2; (approximately) -var v3 [10]int // int v3[10]; -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 // unordered_map<string, int>* v7; (approximately) -var v8 func(a int) int // int (*v8)(int a); -</pre> - -<p> -Declarations generally take the form of a keyword followed by the name -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 being declared; see -the <a href="#Interfaces">discussion of interfaces</a>. - -<p> -You can also use a keyword followed by a series of declarations in -parentheses. - -<pre> -var ( - i int - m float64 -) -</pre> - -<p> -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: - -<pre> -func f(i, j, k int, s, t string) -</pre> - -<p> -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. - -<pre> -var v = *p -</pre> - -<p> -See also the <a href="#Constants">discussion of constants, below</a>. -If a variable is not initialized explicitly, the type must be specified. -In that case it will be -implicitly initialized to the type's zero value (0, nil, etc.). There are no -uninitialized variables in Go. - -<p> -Within a function, a short declaration syntax is available with -<code>:=</code> . - -<pre> -v1 := v2 -</pre> - -<p> -This is equivalent to - -<pre> -var v1 = v2 -</pre> - -<p> -Go permits multiple assignments, which are done in parallel. - -<pre> -i, j = j, i // Swap i and j. -</pre> - -<p> -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. - -<pre> -func f() (i int, j int) { ... } -v1, v2 = f() -</pre> - -<p> -Go code uses very few semicolons in practice. Technically, all Go -statements are terminated by a semicolon. However, Go treats the end -of a non-blank line as a semicolon unless the line is clearly -incomplete (the exact rules are -in <a href="go_spec.html#Semicolons">the language specification</a>). -A consequence of this is that in some cases Go does not permit you to -use a line break. For example, you may not write -<pre> -func g() -{ // INVALID -} -</pre> -A semicolon will be inserted after <code>g()</code>, causing it to be -a function declaration rather than a function definition. Similarly, -you may not write -<pre> -if x { -} -else { // INVALID -} -</pre> -A semicolon will be inserted after the <code>}</code> preceding -the <code>else</code>, causing a syntax error. - -<p> -Since semicolons do end statements, you may continue using them as in -C++. However, that is not the recommended style. Idiomatic Go code -omits unnecessary semicolons, which in practice is all of them other -than the initial <code>for</code> loop clause and cases where you want several -short statements on a single line. - -<p> -While we're on the topic, we recommend that rather than worry about -semicolons and brace placement, you format your code with -the <code>gofmt</code> program. That will produce a single standard -Go style, and let you worry about your code rather than your -formatting. While the style may initially seem odd, it is as good as -any other style, and familiarity will lead to comfort. - -<p> -When using a pointer to a struct, you use <code>.</code> instead -of <code>-></code>. -Thus syntactically speaking a structure and a pointer to a structure -are used in the same way. - -<pre> -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) -</pre> - -<p> -Go does not require parentheses around the condition of a <code>if</code> -statement, or the expressions of a <code>for</code> statement, or the value of a -<code>switch</code> statement. On the other hand, it does require curly braces -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 a parenthesized expression) -if (a < b) f() // INVALID -for i = 0; i < 10; i++ {} // Valid -for (i = 0; i < 10; i++) {} // INVALID -</pre> - -<p> -Go does not have a <code>while</code> statement nor does it have a -<code>do/while</code> -statement. The <code>for</code> statement may be used with a single condition, -which makes it equivalent to a <code>while</code> statement. Omitting the -condition entirely is an endless loop. - -<p> -Go permits <code>break</code> and <code>continue</code> to specify a label. -The label must -refer to a <code>for</code>, <code>switch</code>, or <code>select</code> -statement. - -<p> -In a <code>switch</code> statement, <code>case</code> labels do not fall -through. You can -make them fall through using the <code>fallthrough</code> keyword. This applies -even to adjacent cases. - -<pre> -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. -} -</pre> - -<p> -The values in a <code>case</code> 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 <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() -} -</pre> - -<p> -The <code>++</code> and <code>--</code> operators may only be used in -statements, not in expressions. -You cannot write <code>c = *p++</code>. <code>*p++</code> is parsed as -<code>(*p)++</code>. - -<p> -The <code>defer</code> statement may be used to call a function after -the function containing the <code>defer</code> statement returns. - -<pre> -fd := open("filename") -defer close(fd) // fd will be closed when this function returns. -</pre> - -<h2 id="Constants">Constants </h2> - -<p> -In Go constants may be <i>untyped</i>. This applies even to constants -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 -is used within a context that -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 -</pre> - -<p> -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. - -<pre> -const huge = 1 << 100 -f(huge >> 98) -</pre> - -<p> -Go does not support enums. Instead, you can use the special name -<code>iota</code> in a single <code>const</code> declaration to get a -series of increasing -value. When an initialization expression is omitted for a <code>const</code>, -it reuses the preceding expression. - -<pre> -const ( - red = iota // red == 0 - blue // blue == 1 - green // green == 2 -) -</pre> - -<h2 id="Slices">Slices</h2> - -<p> -A slice is conceptually a struct with three fields: a -pointer to an array, a length, and a capacity. -Slices support -the <code>[]</code> operator to access elements of the underlying array. -The builtin -<code>len</code> function returns the -length of the slice. The builtin <code>cap</code> function returns the -capacity. - -<p> -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 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 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. -If you create a value of type <code>[100]byte</code> (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 <code>[]byte</code>, and pass the -address -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>. - -<p> -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. - -<h2 id="Making_values">Making values</h2> - -<p> -Go has a builtin function <code>new</code> which takes a type and -allocates space -on the heap. The allocated space will be zero-initialized for the type. -For example, <code>new(int)</code> allocates a new int on the heap, -initializes it with the value <code>0</code>, -and returns its address, which has type <code>*int</code>. -Unlike in C++, <code>new</code> is a function, not an operator; -<code>new int</code> is a syntax error. - -<p> -Map and channel values must be allocated using the builtin function -<code>make</code>. -A variable declared with map or channel type without an initializer will be -automatically initialized to <code>nil</code>. -Calling <code>make(map[int]int)</code> returns a newly allocated value of -type <code>map[int]int</code>. -Note that <code>make</code> returns a value, not a pointer. This is -consistent with -the fact that map and channel values are passed by reference. Calling -<code>make</code> with -a map type takes an optional argument which is the expected capacity of the -map. Calling <code>make</code> with a channel type takes an optional -argument which sets the -buffering capacity of the channel; the default is 0 (unbuffered). - -<p> -The <code>make</code> 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, -<code>make([]int, 10, 20)</code>. This is identical to -<code>new([20]int)[0:10]</code>. Since -Go uses garbage collection, the newly allocated array will be discarded -sometime after there are no references to the returned slice. - -<h2 id="Interfaces">Interfaces</h2> - -<p> -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. - -<p> -A method looks like an ordinary function definition, except that it -has a <em>receiver</em>. The receiver is similar to -the <code>this</code> pointer in a C++ class method. - -<pre> -type myType struct { i int } -func (p *myType) get() int { return p.i } -</pre> - -<p> -This declares a method <code>get</code> associated with <code>myType</code>. -The receiver is named <code>p</code> in the body of the function. - -<p> -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. - -<p> -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. - -<pre> -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. -</pre> - -<p> -Given this interface: - -<pre> -type myInterface interface { - get() int - set(i int) -} -</pre> - -<p> -we can make <code>myType</code> satisfy the interface by adding - -<pre> -func (p *myType) set(i int) { p.i = i } -</pre> - -<p> -Now any function which takes <code>myInterface</code> as a parameter -will accept a -variable of type <code>*myType</code>. - -<pre> -func getAndSet(x myInterface) {} -func f1() { - var p myType - getAndSet(&p) -} -</pre> - -<p> -In other words, if we view <code>myInterface</code> as a C++ pure abstract -base -class, defining <code>set</code> and <code>get</code> for -<code>*myType</code> made <code>*myType</code> automatically -inherit from <code>myInterface</code>. A type may satisfy multiple interfaces. - -<p> -An anonymous field may be used to implement something much like a C++ child -class. - -<pre> -type myChildType struct { myType; j int } -func (p *myChildType) get() int { p.j++; return p.myType.get() } -</pre> - -<p> -This effectively implements <code>myChildType</code> as a child of -<code>myType</code>. - -<pre> -func f2() { - var p myChildType - getAndSet(&p) -} -</pre> - -<p> -The <code>set</code> method is effectively inherited from -<code>myChildType</code>, because -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>. -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 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 -different interface type using a special construct called a type assertion. -This is implemented dynamically -at run time, like C++ <code>dynamic_cast</code>. Unlike -<code>dynamic_cast</code>, there does -not need to be any declared relationship between the two interfaces. - -<pre> -type myPrintInterface interface { - print() -} -func f3(x myInterface) { - x.(myPrintInterface).print() // type assertion to myPrintInterface -} -</pre> - -<p> -The conversion to <code>myPrintInterface</code> is entirely dynamic. -It will -work as long as the underlying type of x (the <em>dynamic type</em>) defines -a <code>print</code> method. - -<p> -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. - -<pre> -type Any interface { } -</pre> - -<p> -Containers may be written in terms of <code>Any</code>, 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 run time, but all operations will involve a function call. - -<pre> -type iterator interface { - get() Any - set(v Any) - increment() - equal(arg *iterator) bool -} -</pre> - -<h2 id="Goroutines">Goroutines</h2> - -<p> -Go permits starting a new thread of execution (a <em>goroutine</em>) -using the <code>go</code> -statement. The <code>go</code> statement runs a function in a -different, newly created, goroutine. -All goroutines in a single program share the same address space. - -<p> -Internally, goroutines act like coroutines that are multiplexed among -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) -</pre> - -<p> -(Note that the <code>for</code> statement in the <code>server</code> -function is equivalent to a C++ <code>while (true)</code> loop.) - -<p> -Goroutines are (intended to be) cheap. - -<p> -Function literals (which Go implements as closures) -can be useful with the <code>go</code> statement. - -<pre> -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. -</pre> - -<h2 id="Channels">Channels</h2> - -<p> -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 <code><-</code> as a binary -operator. To -receive a value on a channel, use <code><-</code> as a unary operator. -When calling -functions, channels are passed by reference. - -<p> -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. - -<pre> -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 } - } -} -</pre> - -<p> -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 } -func manager2(ch chan cmd2) { - var val int = 0 - for { - c := <- ch - if c.get { c.ch <- val } - else { val = c.val } - } -} -</pre> - -<p> -To use <code>manager2</code>, given a channel to it: - -<pre> -func f4(ch <- chan cmd2) int { - myCh := make(chan int) - c := cmd2{ true, 0, myCh } // Composite literal syntax. - ch <- c - return <-myCh -} -</pre> |