diff options
author | Ian Lance Taylor <iant@golang.org> | 2009-10-12 15:43:13 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2009-10-12 15:43:13 -0700 |
commit | e7991128077a2b6095899a84385532fd32c9e7a3 (patch) | |
tree | fd81a8070f00404886773f80c59602121bb2ae7d | |
parent | 9b1a9bf3d5632448c69a5de476fcb2c4ddff7734 (diff) | |
download | golang-e7991128077a2b6095899a84385532fd32c9e7a3.tar.gz |
Review and update. No major changes, lots of minor tweaks.
R=go-dev
DELTA=176 (39 added, 9 deleted, 128 changed)
OCL=35612
CL=35623
-rw-r--r-- | doc/go_for_cpp_programmers.html | 228 |
1 files changed, 129 insertions, 99 deletions
diff --git a/doc/go_for_cpp_programmers.html b/doc/go_for_cpp_programmers.html index d6d4329ba..ccd7db562 100644 --- a/doc/go_for_cpp_programmers.html +++ b/doc/go_for_cpp_programmers.html @@ -34,23 +34,25 @@ There is more <a href="./">documentation about go</a>. 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, rather than arrays. This is discussed further - below. + 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 change once they +<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>Processes, and communication channels between them, are provided by - the language. This is discussed further below. +<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, channels, and slices, all described further below) +<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. + 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 @@ -86,7 +88,7 @@ var v3 [10]int; // int v3[10]; var v4 []int; // approximately int* v4; 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 v7 map[string]int; // approximately unordered_map<string, int>* v7; var v8 func(a int) int; // int (*v8)(int a); </pre> @@ -97,7 +99,7 @@ of the object being declared. The keyword is one of <code>var</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 discussion of interfaces. +the <a href="#Interfaces">discussion of interfaces</a>. <p> You can also use a keyword followed by a series of declarations in @@ -108,7 +110,7 @@ var (i int; m float) </pre> <p> -When declaring a function, you must provide a name for each parameter +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: @@ -174,24 +176,15 @@ always <em>permitted</em> at the end of a statement, so you can continue using them as in C++. <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 -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++. - -<p> -When using a pointer, you use <code>.</code> instead of <code>-></code>. -Thus syntactically -speaking there is no difference between a structure and a pointer to a -structure. +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 my_struct struct { i int } -var v9 my_struct; // v9 has structure type -var p9 *my_struct; // p9 is a pointer to a structure +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> @@ -238,10 +231,10 @@ 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; +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> +pointers, can be used—and if the <code>switch</code> value is omitted it defaults to <code>true</code>. <pre> @@ -254,6 +247,15 @@ 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> @@ -292,8 +294,11 @@ const ( red = iota; blue; green ) // red == 0, blue == 1, green == 2 <h2 id="Slices">Slices</h2> <p> -A slice is a pointer to an array, a length, and a capacity. Slices support -the <code>[]</code> operator to access elements. The builtin +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. @@ -383,82 +388,100 @@ entirely separate from the interface itself. <p> A method looks like an ordinary function definition, except that it -has a receiver. The receiver is similar to the <code>this</code> pointer in a -C++ class method. +has a <em>receiver</em>. The receiver is similar to +the <code>this</code> pointer in a C++ class method. <pre> -type my_type struct { i int } -func (p *my_type) get() int { return p.i } +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>my_type</code>. +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 my_interface interface { - get() int; - set(i int); +type myInterface interface { + get() int; + set(i int); } </pre> <p> -we can make <code>my_type</code> satisfy the interface by additionally writing +we can make <code>myType</code> satisfy the interface by additionally writing <pre> -func (p *my_type) set(i int) { p.i = i } +func (p *myType) set(i int) { p.i = i } </pre> <p> -Now any function which takes <code>my_interface</code> as a parameter +Now any function which takes <code>myInterface</code> as a parameter will accept a -variable of type <code>*my_type</code>. +variable of type <code>*myType</code>. <pre> -func get_and_set(x my_interface); +func getAndSet(x myInterface); func f1() { - var p my_type; - get_and_set(&p); + var p myType; + getAndSet(&p); } </pre> <p> -In other words, if we view <code>my_interface</code> as a C++ pure abstract +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>*my_type</code> made <code>*my_type</code> automatically -inherit from <code>my_interface</code>. A type may satisfy multiple interfaces. +<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 my_child_type struct { my_type; j int } -func (p *my_child_type) get() int { p.j++; return (&p.my_type).get() } +type myChildType struct { myType; j int } +func (p *myChildType) get() int { p.j++; return (&p.myType).get() } </pre> <p> -This effectively implements <code>my_child_type</code> as a child of -<code>my_type</code>. +This effectively implements <code>myChildType</code> as a child of +<code>myType</code>. <pre> func f2() { - var p my_child_type; - get_and_set(&p) + var p myChildType; + getAndSet(&p) } </pre> <p> The <code>set</code> method is effectively inherited from -<code>my_child_type</code>, because +<code>myChildType</code>, because methods associated with the anonymous type are promoted to become methods -of the enclosing type. In this case, because <code>my_child_type</code> has an -anonymous field of type <code>my_type</code>, the methods of -<code>my_type</code> also become methods of <code>my_child_type</code>. +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. @@ -478,23 +501,23 @@ at runtime, like C++ <code>dynamic_cast</code>. Unlike not need to be any declared relationship between the two interfaces. <pre> -type my_compare_interface interface { +type myCompareInterface interface { print(); } -func f3(x my_interface) { - x.(my_compare_interface).print() +func f3(x myInterface) { + x.(myCompareInterface).print() } </pre> <p> -The conversion to <code>my_compare_interface</code> is entirely dynamic. +The conversion to <code>myCompareInterface</code> is entirely dynamic. It will -work as long as the underlying type of x (the "dynamic type") defines +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, e.g., +programming similar to templates in C++. This is done by manipulating values of the minimal interface. <pre> @@ -510,19 +533,26 @@ at runtime, but all operations will involve a function call. <pre> type iterator interface { - get() Any; - set(v Any); - increment(); - equal(arg *iterator) bool; + get() Any; + set(v Any); + increment(); + equal(arg *iterator) bool; } </pre> -<h2 id="Processes">Processes</h2> +<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> -Go permits starting a new process (a "goroutine") using the <code>go</code> -statement. The go statement runs a function in a different process. -All processes in a single program share the same address space. +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) } } @@ -534,7 +564,7 @@ go server(1); go server(2); function is equivalent to a C++ <code>while (true)</code> loop). <p> -Processes are (intended to be) cheap. +Goroutines are (intended to be) cheap. <p> Function literals can be useful with the <code>go</code> statement. @@ -542,16 +572,16 @@ Function literals can be useful with the <code>go</code> statement. <pre> var g int // global variable go func(i int) { - s := 0 - for j := 0; j < i; j++ { s += j } - g = s + 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 processes. Any value may be +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 @@ -561,38 +591,38 @@ functions, channels are passed by reference. <p> The Go library provides mutexes, but you can also use -a single process with a shared channel. +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 } - } + 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 -means that if two processes try to retrieve the value at the same -time, the first process may read the response which was triggered by -the second process's request. In simple cases that is fine. For more +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. <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 } - } + var val int = 0; + for { + c := <- ch + if c.get { c.ch <- val } + else { val = c.val } + } } </pre> @@ -601,9 +631,9 @@ To use manager2, given a channel to it: <pre> func f4(ch <- chan cmd2) int { - my_ch := make(chan int); - c := cmd2 { true, 0, my_ch }; // Composite literal syntax. - ch <- c; - return <- my_ch; + myCh := make(chan int); + c := cmd2{ true, 0, myCh }; // Composite literal syntax. + ch <- c; + return <- myCh; } </pre> |