mirror of
https://github.com/golang/go
synced 2024-11-14 07:00:21 -07:00
doc: update Go For C++ Programmers
Minor cleanups to look more like current Go. R=golang-dev, r CC=golang-dev https://golang.org/cl/5707053
This commit is contained in:
parent
9e7e6d9ea4
commit
b69fa69a8b
@ -8,16 +8,19 @@ systems language, like C++.
|
|||||||
These are some notes on Go for experienced C++ programmers. This
|
These are some notes on Go for experienced C++ programmers. This
|
||||||
document discusses the differences between Go and C++, and says little
|
document discusses the differences between Go and C++, and says little
|
||||||
to nothing about the similarities.
|
to nothing about the similarities.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
For a more general introduction to Go, see the
|
For a more general introduction to Go, see the
|
||||||
<a href="http://tour.golang.org/">Go Tour</a>,
|
<a href="http://tour.golang.org/">Go Tour</a>,
|
||||||
<a href="/doc/code.html">How to Write Go Code</a>
|
<a href="/doc/code.html">How to Write Go Code</a>
|
||||||
and <a href="effective_go.html">Effective Go</a>.
|
and <a href="effective_go.html">Effective Go</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
For a detailed description of the Go language, see the
|
For a detailed description of the Go language, see the
|
||||||
<a href="go_spec.html">Go spec</a>.
|
<a href="go_spec.html">Go spec</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="Conceptual_Differences">Conceptual Differences</h2>
|
<h2 id="Conceptual_Differences">Conceptual Differences</h2>
|
||||||
|
|
||||||
@ -29,8 +32,7 @@ For a detailed description of the Go language, see the
|
|||||||
Interfaces are also used where C++ uses templates.
|
Interfaces are also used where C++ uses templates.
|
||||||
|
|
||||||
<li>Go uses garbage collection. It is not necessary (or possible)
|
<li>Go uses garbage collection. It is not necessary (or possible)
|
||||||
to release memory explicitly. The garbage collection is (intended to be)
|
to release memory explicitly.
|
||||||
incremental and highly efficient on modern processors.
|
|
||||||
|
|
||||||
<li>Go has pointers but not 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.
|
use a pointer variable to walk through the bytes of a string.
|
||||||
@ -81,6 +83,7 @@ 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
|
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
|
the way in which the variable is used. Type declarations may be read
|
||||||
easily from left to right.
|
easily from left to right.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<b>Go C++</b>
|
<b>Go C++</b>
|
||||||
@ -102,10 +105,12 @@ of the object being declared. The keyword is one of <code>var</code>,
|
|||||||
exception in that
|
exception in that
|
||||||
the receiver appears before the name of the object being declared; see
|
the receiver appears before the name of the object being declared; see
|
||||||
the <a href="#Interfaces">discussion of interfaces</a>.
|
the <a href="#Interfaces">discussion of interfaces</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can also use a keyword followed by a series of declarations in
|
You can also use a keyword followed by a series of declarations in
|
||||||
parentheses.
|
parentheses.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var (
|
var (
|
||||||
@ -118,6 +123,7 @@ var (
|
|||||||
When declaring a function, you must either 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
|
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:
|
and provide others. You may group several names with the same type:
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func f(i, j, k int, s, t string)
|
func f(i, j, k int, s, t string)
|
||||||
@ -128,6 +134,7 @@ 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
|
specifying the type is permitted but not required. When the type is
|
||||||
not specified, the type of the variable is the type of the
|
not specified, the type of the variable is the type of the
|
||||||
initialization expression.
|
initialization expression.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var v = *p
|
var v = *p
|
||||||
@ -137,12 +144,15 @@ var v = *p
|
|||||||
See also the <a href="#Constants">discussion of constants, below</a>.
|
See also the <a href="#Constants">discussion of constants, below</a>.
|
||||||
If a variable is not initialized explicitly, the type must be specified.
|
If a variable is not initialized explicitly, the type must be specified.
|
||||||
In that case it will be
|
In that case it will be
|
||||||
implicitly initialized to the type's zero value (0, nil, etc.). There are no
|
implicitly initialized to the type's zero value
|
||||||
|
(<code>0</code>, <code>nil</code>, etc.). There are no
|
||||||
uninitialized variables in Go.
|
uninitialized variables in Go.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Within a function, a short declaration syntax is available with
|
Within a function, a short declaration syntax is available with
|
||||||
<code>:=</code> .
|
<code>:=</code> .
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
v1 := v2
|
v1 := v2
|
||||||
@ -150,6 +160,7 @@ v1 := v2
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
This is equivalent to
|
This is equivalent to
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var v1 = v2
|
var v1 = v2
|
||||||
@ -157,6 +168,7 @@ var v1 = v2
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Go permits multiple assignments, which are done in parallel.
|
Go permits multiple assignments, which are done in parallel.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
i, j = j, i // Swap i and j.
|
i, j = j, i // Swap i and j.
|
||||||
@ -166,6 +178,7 @@ i, j = j, i // Swap i and j.
|
|||||||
Functions may have multiple return values, indicated by a list in
|
Functions may have multiple return values, indicated by a list in
|
||||||
parentheses. The returned values can be stored by assignment
|
parentheses. The returned values can be stored by assignment
|
||||||
to a list of variables.
|
to a list of variables.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func f() (i int, j int) { ... }
|
func f() (i int, j int) { ... }
|
||||||
@ -180,22 +193,27 @@ incomplete (the exact rules are
|
|||||||
in <a href="go_spec.html#Semicolons">the language specification</a>).
|
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
|
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
|
use a line break. For example, you may not write
|
||||||
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
func g()
|
func g()
|
||||||
{ // INVALID
|
{ // INVALID
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
<p>
|
||||||
A semicolon will be inserted after <code>g()</code>, causing it to be
|
A semicolon will be inserted after <code>g()</code>, causing it to be
|
||||||
a function declaration rather than a function definition. Similarly,
|
a function declaration rather than a function definition. Similarly,
|
||||||
you may not write
|
you may not write
|
||||||
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
if x {
|
if x {
|
||||||
}
|
}
|
||||||
else { // INVALID
|
else { // INVALID
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
<p>
|
||||||
A semicolon will be inserted after the <code>}</code> preceding
|
A semicolon will be inserted after the <code>}</code> preceding
|
||||||
the <code>else</code>, causing a syntax error.
|
the <code>else</code>, causing a syntax error.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Since semicolons do end statements, you may continue using them as in
|
Since semicolons do end statements, you may continue using them as in
|
||||||
@ -203,6 +221,7 @@ C++. However, that is not the recommended style. Idiomatic Go code
|
|||||||
omits unnecessary semicolons, which in practice is all of them other
|
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
|
than the initial <code>for</code> loop clause and cases where you want several
|
||||||
short statements on a single line.
|
short statements on a single line.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
While we're on the topic, we recommend that rather than worry about
|
While we're on the topic, we recommend that rather than worry about
|
||||||
@ -211,12 +230,14 @@ the <code>gofmt</code> program. That will produce a single standard
|
|||||||
Go style, and let you worry about your code rather than your
|
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
|
formatting. While the style may initially seem odd, it is as good as
|
||||||
any other style, and familiarity will lead to comfort.
|
any other style, and familiarity will lead to comfort.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
When using a pointer to a struct, you use <code>.</code> instead
|
When using a pointer to a struct, you use <code>.</code> instead
|
||||||
of <code>-></code>.
|
of <code>-></code>.
|
||||||
Thus syntactically speaking a structure and a pointer to a structure
|
Thus syntactically speaking a structure and a pointer to a structure
|
||||||
are used in the same way.
|
are used in the same way.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type myStruct struct { i int }
|
type myStruct struct { i int }
|
||||||
@ -230,6 +251,7 @@ Go does not require parentheses around the condition of an <code>if</code>
|
|||||||
statement, or the expressions of a <code>for</code> statement, or the value of a
|
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
|
<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.
|
around the body of an <code>if</code> or <code>for</code> statement.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
if a < b { f() } // Valid
|
if a < b { f() } // Valid
|
||||||
@ -245,18 +267,21 @@ Go does not have a <code>while</code> statement nor does it have a
|
|||||||
statement. The <code>for</code> statement may be used with a single condition,
|
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
|
which makes it equivalent to a <code>while</code> statement. Omitting the
|
||||||
condition entirely is an endless loop.
|
condition entirely is an endless loop.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Go permits <code>break</code> and <code>continue</code> to specify a label.
|
Go permits <code>break</code> and <code>continue</code> to specify a label.
|
||||||
The label must
|
The label must
|
||||||
refer to a <code>for</code>, <code>switch</code>, or <code>select</code>
|
refer to a <code>for</code>, <code>switch</code>, or <code>select</code>
|
||||||
statement.
|
statement.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In a <code>switch</code> statement, <code>case</code> labels do not fall
|
In a <code>switch</code> statement, <code>case</code> labels do not fall
|
||||||
through. You can
|
through. You can
|
||||||
make them fall through using the <code>fallthrough</code> keyword. This applies
|
make them fall through using the <code>fallthrough</code> keyword. This applies
|
||||||
even to adjacent cases.
|
even to adjacent cases.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
switch i {
|
switch i {
|
||||||
@ -268,6 +293,7 @@ case 1:
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
But a <code>case</code> can have multiple values.
|
But a <code>case</code> can have multiple values.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
switch i {
|
switch i {
|
||||||
@ -282,6 +308,7 @@ any type
|
|||||||
that supports the equality comparison operator, such as strings or
|
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>.
|
value is omitted it defaults to <code>true</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
switch {
|
switch {
|
||||||
@ -299,10 +326,12 @@ The <code>++</code> and <code>--</code> operators may only be used in
|
|||||||
statements, not in expressions.
|
statements, not in expressions.
|
||||||
You cannot write <code>c = *p++</code>. <code>*p++</code> is parsed as
|
You cannot write <code>c = *p++</code>. <code>*p++</code> is parsed as
|
||||||
<code>(*p)++</code>.
|
<code>(*p)++</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The <code>defer</code> statement may be used to call a function after
|
The <code>defer</code> statement may be used to call a function after
|
||||||
the function containing the <code>defer</code> statement returns.
|
the function containing the <code>defer</code> statement returns.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
fd := open("filename")
|
fd := open("filename")
|
||||||
@ -320,6 +349,7 @@ A value derived from an untyped constant becomes typed when it
|
|||||||
is used within a context that
|
is used within a context that
|
||||||
requires a typed value. This permits constants to be used relatively
|
requires a typed value. This permits constants to be used relatively
|
||||||
freely without requiring general implicit type conversion.
|
freely without requiring general implicit type conversion.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var a uint
|
var a uint
|
||||||
@ -330,6 +360,7 @@ f(a + 1) // untyped numeric constant "1" becomes typed as uint
|
|||||||
The language does not impose any limits on the size of an untyped
|
The language does not impose any limits on the size of an untyped
|
||||||
numeric constant or constant expression. A limit is only applied when
|
numeric constant or constant expression. A limit is only applied when
|
||||||
a constant is used where a type is required.
|
a constant is used where a type is required.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
const huge = 1 << 100
|
const huge = 1 << 100
|
||||||
@ -342,6 +373,7 @@ Go does not support enums. Instead, you can use the special name
|
|||||||
series of increasing
|
series of increasing
|
||||||
value. When an initialization expression is omitted for a <code>const</code>,
|
value. When an initialization expression is omitted for a <code>const</code>,
|
||||||
it reuses the preceding expression.
|
it reuses the preceding expression.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
const (
|
const (
|
||||||
@ -362,40 +394,43 @@ The builtin
|
|||||||
<code>len</code> function returns the
|
<code>len</code> function returns the
|
||||||
length of the slice. The builtin <code>cap</code> function returns the
|
length of the slice. The builtin <code>cap</code> function returns the
|
||||||
capacity.
|
capacity.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Given an array, or another slice, a new slice is created via
|
Given an array, or another slice, a new slice is created via
|
||||||
<code>a[I:J]</code>. This
|
<code>a[i:j]</code>. This
|
||||||
creates a new slice which refers to <code>a</code>, starts at
|
creates a new slice which refers to <code>a</code>, starts at
|
||||||
index <code>I</code>, and ends before index
|
index <code>i</code>, and ends before index
|
||||||
<code>J</code>. It has length <code>J - I</code>.
|
<code>j</code>. It has length <code>j-i</code>.
|
||||||
|
If <code>i</code> is omitted, the slice starts at <code>0</code>.
|
||||||
|
If <code>j</code> is omitted, the slice ends at <code>len(a)</code>.
|
||||||
The new slice refers to the same array
|
The new slice refers to the same array
|
||||||
to which <code>a</code>
|
to which <code>a</code>
|
||||||
refers. That is, changes made using the new slice may be seen using
|
refers. That is, changes made using the new slice may be seen using
|
||||||
<code>a</code>. The
|
<code>a</code>. The
|
||||||
capacity of the new slice is simply the capacity of <code>a</code> minus
|
capacity of the new slice is simply the capacity of <code>a</code> minus
|
||||||
<code>I</code>. The capacity
|
<code>i</code>. The capacity
|
||||||
of an array is the length of the array. You may also assign an array pointer
|
of an array is the length of the array.
|
||||||
to a variable of slice type; given <code>var s []int; var a[10] int</code>,
|
</p>
|
||||||
the assignment <code>s = &a</code> is equivalent to
|
|
||||||
<code>s = a[0:len(a)]</code>.
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
What this means is that Go uses slices for some cases where C++ uses pointers.
|
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,
|
If you create a value of type <code>[100]byte</code> (an array of 100 bytes,
|
||||||
perhaps a
|
perhaps a
|
||||||
buffer) and you want to pass it to a function without copying it, you should
|
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
|
declare the function parameter to have type <code>[]byte</code>, and
|
||||||
address
|
pass a slice of the array (<code>a[:]</code> will pass the entire array).
|
||||||
of the array. Unlike in C++, it is not
|
Unlike in C++, it is not
|
||||||
necessary to pass the length of the buffer; it is efficiently accessible via
|
necessary to pass the length of the buffer; it is efficiently accessible via
|
||||||
<code>len</code>.
|
<code>len</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The slice syntax may also be used with a string. It returns a new string,
|
The slice syntax may also be used with a string. It returns a new string,
|
||||||
whose value is a substring of the original string.
|
whose value is a substring of the original string.
|
||||||
Because strings are immutable, string slices can be implemented
|
Because strings are immutable, string slices can be implemented
|
||||||
without allocating new storage for the slices's contents.
|
without allocating new storage for the slices's contents.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="Making_values">Making values</h2>
|
<h2 id="Making_values">Making values</h2>
|
||||||
|
|
||||||
@ -408,6 +443,33 @@ initializes it with the value <code>0</code>,
|
|||||||
and returns its address, which has type <code>*int</code>.
|
and returns its address, which has type <code>*int</code>.
|
||||||
Unlike in C++, <code>new</code> is a function, not an operator;
|
Unlike in C++, <code>new</code> is a function, not an operator;
|
||||||
<code>new int</code> is a syntax error.
|
<code>new int</code> is a syntax error.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Perhaps surprisingly, <code>new</code> is not commonly used in Go
|
||||||
|
programs. In Go taking the address of a variable is always safe and
|
||||||
|
never yields a dangling pointer. If the program takes the address of
|
||||||
|
a variable, it will be allocated on the heap if necessary. So these
|
||||||
|
functions are equivalent:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
type S { I int }
|
||||||
|
|
||||||
|
func f1() *S {
|
||||||
|
return new(S)
|
||||||
|
}
|
||||||
|
|
||||||
|
func f2() *S {
|
||||||
|
var s S
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func f3() *S {
|
||||||
|
// More idiomatic: use composite literal syntax.
|
||||||
|
return &S{0}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Map and channel values must be allocated using the builtin function
|
Map and channel values must be allocated using the builtin function
|
||||||
@ -424,6 +486,7 @@ 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
|
map. Calling <code>make</code> with a channel type takes an optional
|
||||||
argument which sets the
|
argument which sets the
|
||||||
buffering capacity of the channel; the default is 0 (unbuffered).
|
buffering capacity of the channel; the default is 0 (unbuffered).
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The <code>make</code> function may also be used to allocate a slice.
|
The <code>make</code> function may also be used to allocate a slice.
|
||||||
@ -435,6 +498,7 @@ A second, optional, argument is the capacity of the slice. For example,
|
|||||||
<code>new([20]int)[0:10]</code>. Since
|
<code>new([20]int)[0:10]</code>. Since
|
||||||
Go uses garbage collection, the newly allocated array will be discarded
|
Go uses garbage collection, the newly allocated array will be discarded
|
||||||
sometime after there are no references to the returned slice.
|
sometime after there are no references to the returned slice.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="Interfaces">Interfaces</h2>
|
<h2 id="Interfaces">Interfaces</h2>
|
||||||
|
|
||||||
@ -447,33 +511,38 @@ Go, any type which provides the methods named in the interface may be
|
|||||||
treated as an implementation of the interface. No explicitly declared
|
treated as an implementation of the interface. No explicitly declared
|
||||||
inheritance is required. The implementation of the interface is
|
inheritance is required. The implementation of the interface is
|
||||||
entirely separate from the interface itself.
|
entirely separate from the interface itself.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A method looks like an ordinary function definition, except that it
|
A method looks like an ordinary function definition, except that it
|
||||||
has a <em>receiver</em>. The receiver is similar to
|
has a <em>receiver</em>. The receiver is similar to
|
||||||
the <code>this</code> pointer in a C++ class method.
|
the <code>this</code> pointer in a C++ class method.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type myType struct { i int }
|
type myType struct { i int }
|
||||||
func (p *myType) get() int { return p.i }
|
func (p *myType) Get() int { return p.i }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This declares a method <code>get</code> associated with <code>myType</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.
|
The receiver is named <code>p</code> in the body of the function.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Methods are defined on named types. If you convert the value
|
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,
|
to a different type, the new value will have the methods of the new type,
|
||||||
not the old type.
|
not the old type.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You may define methods on a builtin type by declaring a new named type
|
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.
|
derived from it. The new type is distinct from the builtin type.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type myInteger int
|
type myInteger int
|
||||||
func (p myInteger) get() int { return int(p) } // Conversion required.
|
func (p myInteger) Get() int { return int(p) } // Conversion required.
|
||||||
func f(i int) { }
|
func f(i int) { }
|
||||||
var v myInteger
|
var v myInteger
|
||||||
// f(v) is invalid.
|
// f(v) is invalid.
|
||||||
@ -482,58 +551,64 @@ var v myInteger
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Given this interface:
|
Given this interface:
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type myInterface interface {
|
type myInterface interface {
|
||||||
get() int
|
Get() int
|
||||||
set(i int)
|
Set(i int)
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
we can make <code>myType</code> satisfy the interface by adding
|
we can make <code>myType</code> satisfy the interface by adding
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func (p *myType) set(i int) { p.i = i }
|
func (p *myType) Set(i int) { p.i = i }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Now any function which takes <code>myInterface</code> as a parameter
|
Now any function which takes <code>myInterface</code> as a parameter
|
||||||
will accept a
|
will accept a
|
||||||
variable of type <code>*myType</code>.
|
variable of type <code>*myType</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func getAndSet(x myInterface) {}
|
func GetAndSet(x myInterface) {}
|
||||||
func f1() {
|
func f1() {
|
||||||
var p myType
|
var p myType
|
||||||
getAndSet(&p)
|
GetAndSet(&p)
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In other words, if we view <code>myInterface</code> as a C++ pure abstract
|
In other words, if we view <code>myInterface</code> as a C++ pure abstract
|
||||||
base
|
base
|
||||||
class, defining <code>set</code> and <code>get</code> for
|
class, defining <code>Set</code> and <code>Get</code> for
|
||||||
<code>*myType</code> made <code>*myType</code> automatically
|
<code>*myType</code> made <code>*myType</code> automatically
|
||||||
inherit from <code>myInterface</code>. A type may satisfy multiple interfaces.
|
inherit from <code>myInterface</code>. A type may satisfy multiple interfaces.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
An anonymous field may be used to implement something much like a C++ child
|
An anonymous field may be used to implement something much like a C++ child
|
||||||
class.
|
class.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type myChildType struct { myType; j int }
|
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>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This effectively implements <code>myChildType</code> as a child of
|
This effectively implements <code>myChildType</code> as a child of
|
||||||
<code>myType</code>.
|
<code>myType</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func f2() {
|
func f2() {
|
||||||
var p myChildType
|
var p myChildType
|
||||||
getAndSet(&p)
|
GetAndSet(&p)
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -544,8 +619,9 @@ methods associated with the anonymous field are promoted to become methods
|
|||||||
of the enclosing type. In this case, because <code>myChildType</code> has an
|
of the enclosing type. In this case, because <code>myChildType</code> has an
|
||||||
anonymous field of type <code>myType</code>, the methods of
|
anonymous field of type <code>myType</code>, the methods of
|
||||||
<code>myType</code> also become methods of <code>myChildType</code>.
|
<code>myType</code> also become methods of <code>myChildType</code>.
|
||||||
In this example, the <code>get</code> method was
|
In this example, the <code>Get</code> method was
|
||||||
overridden, and the <code>set</code> method was inherited.
|
overridden, and the <code>Set</code> method was inherited.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This is not precisely the same as a child class in C++.
|
This is not precisely the same as a child class in C++.
|
||||||
@ -553,21 +629,23 @@ When a method of an anonymous field is called,
|
|||||||
its receiver is the field, not the surrounding struct.
|
its receiver is the field, not the surrounding struct.
|
||||||
In other words, methods on anonymous fields are not virtual functions.
|
In other words, methods on anonymous fields are not virtual functions.
|
||||||
When you want the equivalent of a virtual function, use an interface.
|
When you want the equivalent of a virtual function, use an interface.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A variable which has an interface type may be converted to have a
|
A variable that has an interface type may be converted to have a
|
||||||
different interface type using a special construct called a type assertion.
|
different interface type using a special construct called a type assertion.
|
||||||
This is implemented dynamically
|
This is implemented dynamically
|
||||||
at run time, like C++ <code>dynamic_cast</code>. Unlike
|
at run time, like C++ <code>dynamic_cast</code>. Unlike
|
||||||
<code>dynamic_cast</code>, there does
|
<code>dynamic_cast</code>, there does
|
||||||
not need to be any declared relationship between the two interfaces.
|
not need to be any declared relationship between the two interfaces.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type myPrintInterface interface {
|
type myPrintInterface interface {
|
||||||
print()
|
Print()
|
||||||
}
|
}
|
||||||
func f3(x myInterface) {
|
func f3(x myInterface) {
|
||||||
x.(myPrintInterface).print() // type assertion to myPrintInterface
|
x.(myPrintInterface).Print() // type assertion to myPrintInterface
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -576,11 +654,13 @@ The conversion to <code>myPrintInterface</code> is entirely dynamic.
|
|||||||
It will
|
It will
|
||||||
work as long as the underlying type of x (the <em>dynamic type</em>) defines
|
work as long as the underlying type of x (the <em>dynamic type</em>) defines
|
||||||
a <code>print</code> method.
|
a <code>print</code> method.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Because the conversion is dynamic, it may be used to implement generic
|
Because the conversion is dynamic, it may be used to implement generic
|
||||||
programming similar to templates in C++. This is done by
|
programming similar to templates in C++. This is done by
|
||||||
manipulating values of the minimal interface.
|
manipulating values of the minimal interface.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type Any interface { }
|
type Any interface { }
|
||||||
@ -593,16 +673,24 @@ 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
|
than static, there is no equivalent of the way that a C++ template may
|
||||||
inline the relevant operations. The operations are fully type-checked
|
inline the relevant operations. The operations are fully type-checked
|
||||||
at run time, but all operations will involve a function call.
|
at run time, but all operations will involve a function call.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type iterator interface {
|
type Iterator interface {
|
||||||
get() Any
|
Get() Any
|
||||||
set(v Any)
|
Set(v Any)
|
||||||
increment()
|
Increment()
|
||||||
equal(arg *iterator) bool
|
Equal(arg Iterator) bool
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note that <code>Equal</code> has an argument of
|
||||||
|
type <code>Iterator</code>. This does not behave like a C++
|
||||||
|
template. See <a href="go_faq.html#t_and_equal_interface">the
|
||||||
|
FAQ</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="Goroutines">Goroutines</h2>
|
<h2 id="Goroutines">Goroutines</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -611,17 +699,19 @@ using the <code>go</code>
|
|||||||
statement. The <code>go</code> statement runs a function in a
|
statement. The <code>go</code> statement runs a function in a
|
||||||
different, newly created, goroutine.
|
different, newly created, goroutine.
|
||||||
All goroutines in a single program share the same address space.
|
All goroutines in a single program share the same address space.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Internally, goroutines act like coroutines that are multiplexed among
|
Internally, goroutines act like coroutines that are multiplexed among
|
||||||
multiple operating system threads. You do not have to worry
|
multiple operating system threads. You do not have to worry
|
||||||
about these details.
|
about these details.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func server(i int) {
|
func server(i int) {
|
||||||
for {
|
for {
|
||||||
print(i)
|
fmt.Print(i)
|
||||||
sys.sleep(10)
|
time.Sleep(10 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go server(1)
|
go server(1)
|
||||||
@ -631,13 +721,16 @@ go server(2)
|
|||||||
<p>
|
<p>
|
||||||
(Note that the <code>for</code> statement in the <code>server</code>
|
(Note that the <code>for</code> statement in the <code>server</code>
|
||||||
function is equivalent to a C++ <code>while (true)</code> loop.)
|
function is equivalent to a C++ <code>while (true)</code> loop.)
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Goroutines are (intended to be) cheap.
|
Goroutines are (intended to be) cheap.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Function literals (which Go implements as closures)
|
Function literals (which Go implements as closures)
|
||||||
can be useful with the <code>go</code> statement.
|
can be useful with the <code>go</code> statement.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var g int
|
var g int
|
||||||
@ -658,21 +751,23 @@ operator. To
|
|||||||
receive a value on a channel, use <code><-</code> as a unary operator.
|
receive a value on a channel, use <code><-</code> as a unary operator.
|
||||||
When calling
|
When calling
|
||||||
functions, channels are passed by reference.
|
functions, channels are passed by reference.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The Go library provides mutexes, but you can also use
|
The Go library provides mutexes, but you can also use
|
||||||
a single goroutine 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
|
Here is an example of using a manager function to control access to a
|
||||||
single value.
|
single value.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type cmd struct { get bool; val int }
|
type Cmd struct { Get bool; Val int }
|
||||||
func manager(ch chan cmd) {
|
func Manager(ch chan Cmd) {
|
||||||
var val int = 0
|
val := 0
|
||||||
for {
|
for {
|
||||||
c := <-ch
|
c := <-ch
|
||||||
if c.get { c.val = val; ch <- c }
|
if c.Get { c.Val = val; ch <- c }
|
||||||
else { val = c.val }
|
else { val = c.Val }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
@ -684,26 +779,28 @@ with the manager at once: a goroutine waiting for a response
|
|||||||
from the manager might receive a request from another goroutine
|
from the manager might receive a request from another goroutine
|
||||||
instead.
|
instead.
|
||||||
A solution is to pass in a channel.
|
A solution is to pass in a channel.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type cmd2 struct { get bool; val int; ch <- chan int }
|
type Cmd2 struct { Get bool; Val int; Ch <- chan int }
|
||||||
func manager2(ch chan cmd2) {
|
func Manager2(ch chan Cmd2) {
|
||||||
var val int = 0
|
val := 0
|
||||||
for {
|
for {
|
||||||
c := <-ch
|
c := <-ch
|
||||||
if c.get { c.ch <- val }
|
if c.Get { c.ch <- val }
|
||||||
else { val = c.val }
|
else { val = c.Val }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To use <code>manager2</code>, given a channel to it:
|
To use <code>Manager2</code>, given a channel to it:
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func f4(ch <- chan cmd2) int {
|
func f4(ch <- chan Cmd2) int {
|
||||||
myCh := make(chan int)
|
myCh := make(chan int)
|
||||||
c := cmd2{ true, 0, myCh } // Composite literal syntax.
|
c := Cmd2{ true, 0, myCh } // Composite literal syntax.
|
||||||
ch <- c
|
ch <- c
|
||||||
return <-myCh
|
return <-myCh
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user