Commit 489a2632 authored by Rob Pike's avatar Rob Pike

doc: update Concurrency, Functions and Methods, and Control Flow sections

Many parts of the FAQ are dusty and need cleaning up.
This is the first of a series of changes to bring it up to date.
Since it was first written at the time of release, some of the
ideas and background have changed, and some historical
remarks are largely irrelevant now.

Update #26107.

Change-Id: I1f36df7d8ecc8a1a033d5ac4fa1edeece25ed6b4
Reviewed-on: https://go-review.googlesource.com/123496Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 6f8e8e14
...@@ -1407,16 +1407,28 @@ To find the amount of actual memory allocated to a Go process, use the Unix ...@@ -1407,16 +1407,28 @@ To find the amount of actual memory allocated to a Go process, use the Unix
What operations are atomic? What about mutexes?</h3> What operations are atomic? What about mutexes?</h3>
<p> <p>
We haven't fully defined it all yet, but some details about atomicity are A description of the atomicity of operations in Go can be found in
available in the <a href="/ref/mem">Go Memory Model specification</a>. the <a href="/ref/mem">Go Memory Model</a> document.
</p> </p>
<p> <p>
Regarding mutexes, the <a href="/pkg/sync">sync</a> Low-level synchronization and atomic primitives are available in the
package implements them, but we hope Go programming style will <a href="/pkg/sync">sync</a> and
encourage people to try higher-level techniques. In particular, consider <a href="/pkg/sync/atomic">sync/atomic</a>
structuring your program so that only one goroutine at a time is ever packages.
responsible for a particular piece of data. These packages are good for simple tasks such as incrementing
reference counts or guaranteeing small-scale mutual exclusion.
</p>
<p>
For higher-level operations, such as coordination among
concurrent servers, higher-level techniques can lead
to nicer programs, and Go supports this approach through
its goroutines and channels.
For instance, you can structure your program so that only one
goroutine at a time is ever responsible for a particular piece of data.
That approach is summarized by the original
<a href="https://www.youtube.com/watch?v=PAAkCSZUG1c">Go proverb</a>,
</p> </p>
<p> <p>
...@@ -1424,7 +1436,13 @@ Do not communicate by sharing memory. Instead, share memory by communicating. ...@@ -1424,7 +1436,13 @@ Do not communicate by sharing memory. Instead, share memory by communicating.
</p> </p>
<p> <p>
See the <a href="/doc/codewalk/sharemem/">Share Memory By Communicating</a> code walk and its <a href="//blog.golang.org/2010/07/share-memory-by-communicating.html">associated article</a> for a detailed discussion of this concept. See the <a href="/doc/codewalk/sharemem/">Share Memory By Communicating</a> code walk
and its <a href="//blog.golang.org/2010/07/share-memory-by-communicating.html">
associated article</a> for a detailed discussion of this concept.
</p>
<p>
Large concurrent programs are likely to borrow from both these toolkits.
</p> </p>
<h3 id="Why_no_multi_CPU"> <h3 id="Why_no_multi_CPU">
...@@ -1432,15 +1450,17 @@ Why doesn't my multi-goroutine program use multiple CPUs?</h3> ...@@ -1432,15 +1450,17 @@ Why doesn't my multi-goroutine program use multiple CPUs?</h3>
<p> <p>
The number of CPUs available simultaneously to executing goroutines is The number of CPUs available simultaneously to executing goroutines is
controlled by the <code>GOMAXPROCS</code> shell environment variable. controlled by the <code>GOMAXPROCS</code> shell environment variable,
In earlier releases of Go, the default value was 1, but as of Go 1.5 the default whose default value is the number of CPU cores available.
value is the number of cores available. Programs with the potential for parallel execution should therefore
Therefore programs compiled after 1.5 should demonstrate parallel execution achieve it by default on a multiple-CPU machine.
of multiple goroutines. To change the number of parallel CPUs to use,
To change the behavior, set the environment variable or use the similarly-named set the environment variable or use the similarly-named
<a href="/pkg/runtime/#GOMAXPROCS">function</a> <a href="/pkg/runtime/#GOMAXPROCS">function</a>
of the runtime package to configure the of the runtime package to configure the
run-time support to utilize a different number of threads. run-time support to utilize a different number of threads.
Setting it to 1 eliminates the possibility of true parallelism,
forcing independent goroutines to take turns executing.
</p> </p>
<p> <p>
...@@ -1465,10 +1485,10 @@ intrinsically parallel. ...@@ -1465,10 +1485,10 @@ intrinsically parallel.
<p> <p>
In practical terms, programs that spend more time In practical terms, programs that spend more time
communicating on channels than doing computation synchronizing or communicating than doing useful computation
may experience performance degradation when using may experience performance degradation when using
multiple OS threads. multiple OS threads.
This is because sending data between threads involves switching This is because passing data between threads involves switching
contexts, which has significant cost. contexts, which has significant cost.
For instance, the <a href="/ref/spec#An_example_package">prime sieve example</a> For instance, the <a href="/ref/spec#An_example_package">prime sieve example</a>
from the Go specification has no significant parallelism although it launches many from the Go specification has no significant parallelism although it launches many
...@@ -1542,21 +1562,26 @@ used in flexible ways to interact with it. ...@@ -1542,21 +1562,26 @@ used in flexible ways to interact with it.
Why do T and *T have different method sets?</h3> Why do T and *T have different method sets?</h3>
<p> <p>
From the <a href="/ref/spec#Types">Go Spec</a>: As the <a href="/ref/spec#Types">Go specification</a> says,
the method set of a type <code>T</code> consists of all methods
with receiver type <code>T</code>,
while that of the corresponding pointer
type <code>*T</code> consists of all methods with receiver <code>*T</code> or
<code>T</code>.
That means the method set of <code>*T</code>
includes that of <code>T</code>),
but not the reverse.
</p> </p>
<blockquote>
The method set of any other named type <code>T</code> consists of all methods
with receiver type <code>T</code>. The method set of the corresponding pointer
type <code>*T</code> is the set of all methods with receiver <code>*T</code> or
<code>T</code> (that is, it also contains the method set of <code>T</code>).
</blockquote>
<p> <p>
If an interface value contains a pointer <code>*T</code>, This distinction arises because
if an interface value contains a pointer <code>*T</code>,
a method call can obtain a value by dereferencing the pointer, a method call can obtain a value by dereferencing the pointer,
but if an interface value contains a value <code>T</code>, but if an interface value contains a value <code>T</code>,
there is no useful way for a method call to obtain a pointer. there is no safe way for a method call to obtain a pointer.
(Doing so would allow a method to modify the contents of
the value inside the interface, which is not permitted by
the language specification.)
</p> </p>
<p> <p>
...@@ -1654,13 +1679,21 @@ seem odd but works fine in Go: ...@@ -1654,13 +1679,21 @@ seem odd but works fine in Go:
} }
</pre> </pre>
<p>
This behavior of the language, not defining a new variable for
each iteration, may have been a mistake in retrospect.
It may be addressed in a later version but, for compatibility,
cannot change in Go version 1.
</p>
<h2 id="Control_flow">Control flow</h2> <h2 id="Control_flow">Control flow</h2>
<h3 id="Does_Go_have_a_ternary_form"> <h3 id="Does_Go_have_a_ternary_form">
Does Go have the <code>?:</code> operator?</h3> Why does Go not have the <code>?:</code> operator?</h3>
<p> <p>
There is no ternary testing operation in Go. You may use the following to achieve the same There is no ternary testing operation in Go.
You may use the following to achieve the same
result: result:
</p> </p>
...@@ -1672,6 +1705,14 @@ if expr { ...@@ -1672,6 +1705,14 @@ if expr {
} }
</pre> </pre>
<p>
The reason <code>?:</code> is absent from Go is that the language's designers
had seen the operation used too often to create impenetrably complex expressions.
The <code>if-else</code> form, although longer,
is unquestionably clearer.
A language needs only one conditional control flow construct.
</p>
<h2 id="Packages_Testing">Packages and Testing</h2> <h2 id="Packages_Testing">Packages and Testing</h2>
<h3 id="How_do_I_create_a_multifile_package"> <h3 id="How_do_I_create_a_multifile_package">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment