diff options
Diffstat (limited to 'doc/go_for_cpp_programmers.html')
-rw-r--r-- | doc/go_for_cpp_programmers.html | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html new file mode 100644 index 000000000..7168f1d05 --- /dev/null +++ b/doc/go_for_cpp_programmers.html @@ -0,0 +1,707 @@ +<!-- 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> |