mirror of
https://github.com/golang/go
synced 2024-11-13 15:00:23 -07:00
FAQ: update to Go 1.
R=adg, rsc, r CC=golang-dev https://golang.org/cl/5562051
This commit is contained in:
parent
93c4e29605
commit
fcfed1479e
138
doc/go_faq.html
138
doc/go_faq.html
@ -190,10 +190,11 @@ easier to understand what happens when things combine.
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Yes. There are now several Go programs deployed in
|
Yes. There are now several Go programs deployed in
|
||||||
production inside Google. For instance, the server behind
|
production inside Google. A public example is the server behind
|
||||||
<a href="http://golang.org">http://golang.org</a> is a Go program;
|
<a href="http://golang.org">http://golang.org</a>.
|
||||||
in fact it's just the <a href="/cmd/godoc"><code>godoc</code></a>
|
It's just the <a href="/cmd/godoc"><code>godoc</code></a>
|
||||||
document server running in a production configuration.
|
document server running in a production configuration on
|
||||||
|
<a href="http://code.google.com/appengine/">Google App Engine</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="Do_Go_programs_link_with_Cpp_programs">
|
<h3 id="Do_Go_programs_link_with_Cpp_programs">
|
||||||
@ -362,7 +363,7 @@ because we feel it's sometimes worth trying a different approach.
|
|||||||
Why build concurrency on the ideas of CSP?</h3>
|
Why build concurrency on the ideas of CSP?</h3>
|
||||||
<p>
|
<p>
|
||||||
Concurrency and multi-threaded programming have a reputation
|
Concurrency and multi-threaded programming have a reputation
|
||||||
for difficulty. We believe the problem is due partly to complex
|
for difficulty. We believe this is due partly to complex
|
||||||
designs such as pthreads and partly to overemphasis on low-level details
|
designs such as pthreads and partly to overemphasis on low-level details
|
||||||
such as mutexes, condition variables, and memory barriers.
|
such as mutexes, condition variables, and memory barriers.
|
||||||
Higher-level interfaces enable much simpler code, even if there are still
|
Higher-level interfaces enable much simpler code, even if there are still
|
||||||
@ -433,7 +434,9 @@ we believe is easy to use and in some ways more general. There are
|
|||||||
also ways to embed types in other types to provide something
|
also ways to embed types in other types to provide something
|
||||||
analogous—but not identical—to subclassing.
|
analogous—but not identical—to subclassing.
|
||||||
Moreover, methods in Go are more general than in C++ or Java:
|
Moreover, methods in Go are more general than in C++ or Java:
|
||||||
they can be defined for any sort of data, not just structs.
|
they can be defined for any sort of data, even built-in types such
|
||||||
|
as plain, “unboxed” integers.
|
||||||
|
They are not restricted to structs (classes).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -446,7 +449,7 @@ How do I get dynamic dispatch of methods?</h3>
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
The only way to have dynamically dispatched methods is through an
|
The only way to have dynamically dispatched methods is through an
|
||||||
interface. Methods on structs or other types are always resolved statically.
|
interface. Methods on a struct or any other concrete type are always resolved statically.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="inheritance">
|
<h3 id="inheritance">
|
||||||
@ -541,7 +544,7 @@ interface <code>I</code> by attempting an assignment:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type T struct{}
|
type T struct{}
|
||||||
var _ I = T{}
|
var _ I = T{} // Verify that T implements I.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -557,8 +560,8 @@ For example:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type Fooer interface {
|
type Fooer interface {
|
||||||
Foo()
|
Foo()
|
||||||
ImplementsFooer()
|
ImplementsFooer()
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -590,7 +593,7 @@ itself with another value:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
type Equaler interface {
|
type Equaler interface {
|
||||||
Equal(Equaler) bool
|
Equal(Equaler) bool
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -673,7 +676,7 @@ slice. This example converts a slice of <code>int</code> to a slice of
|
|||||||
t := []int{1, 2, 3, 4}
|
t := []int{1, 2, 3, 4}
|
||||||
s := make([]interface{}, len(t))
|
s := make([]interface{}, len(t))
|
||||||
for i, v := range t {
|
for i, v := range t {
|
||||||
s[i] = v
|
s[i] = v
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -750,17 +753,22 @@ to write one but it will not be as convenient syntactically; this seems a reason
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="map_keys">
|
<h3 id="map_keys">
|
||||||
Why don't maps allow structs and arrays as keys?</h3>
|
Why don't maps allow slices as keys?</h3>
|
||||||
<p>
|
<p>
|
||||||
Map lookup requires an equality operator, which structs and arrays do not implement.
|
Map lookup requires an equality operator, which slices do not implement.
|
||||||
They don't implement equality because equality is not well defined on such types;
|
They don't implement equality because equality is not well defined on such types;
|
||||||
there are multiple considerations involving shallow vs. deep comparison, pointer vs.
|
there are multiple considerations involving shallow vs. deep comparison, pointer vs.
|
||||||
value comparison, how to deal with recursive structures, and so on.
|
value comparison, how to deal with recursive types, and so on.
|
||||||
We may revisit this issue—and implementing equality for structs and arrays
|
We may revisit this issue—and implementing equality for slices
|
||||||
will not invalidate any existing programs—but without a clear idea of what
|
will not invalidate any existing programs—but without a clear idea of what
|
||||||
equality of structs and arrays should mean, it was simpler to leave it out for now.
|
equality of structs and arrays should mean, it was simpler to leave it out for now.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In Go 1, equality is defined for structs and arrays, so such
|
||||||
|
types can be used as map keys, but slices still do not have a definition of equality.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="references">
|
<h3 id="references">
|
||||||
Why are maps, slices, and channels references while arrays are values?</h3>
|
Why are maps, slices, and channels references while arrays are values?</h3>
|
||||||
<p>
|
<p>
|
||||||
@ -833,7 +841,7 @@ value makes a copy of the pointer, but not the data it points to.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Map and slice values behave like pointers; they are descriptors that
|
Map and slice values behave like pointers: they are descriptors that
|
||||||
contain pointers to the underlying map or slice data. Copying a map or
|
contain pointers to the underlying map or slice data. Copying a map or
|
||||||
slice value doesn't copy the data it points to. Copying an interface value
|
slice value doesn't copy the data it points to. Copying an interface value
|
||||||
makes a copy of the thing stored in the interface value. If the interface
|
makes a copy of the thing stored in the interface value. If the interface
|
||||||
@ -954,6 +962,8 @@ local to a function in that function's stack frame. However, if the
|
|||||||
compiler cannot prove that the variable is not referenced after the
|
compiler cannot prove that the variable is not referenced after the
|
||||||
function returns, then the compiler must allocate the variable on the
|
function returns, then the compiler must allocate the variable on the
|
||||||
garbage-collected heap to avoid dangling pointer errors.
|
garbage-collected heap to avoid dangling pointer errors.
|
||||||
|
Also, if a local variable is very large, it might make more sense
|
||||||
|
to store it on the heap rather than the stack.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -993,10 +1003,8 @@ See the <a href="/doc/codewalk/sharemem/">Share Memory By Communicating</a> code
|
|||||||
Why doesn't my multi-goroutine program use multiple CPUs?</h3>
|
Why doesn't my multi-goroutine program use multiple CPUs?</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Under the gc compilers you must set <code>GOMAXPROCS</code> to allow the
|
You must set <code>GOMAXPROCS</code> to allow the
|
||||||
run-time support to utilise more than one OS thread. Under <code>gccgo</code> an OS
|
run-time support to utilize more than one OS thread.
|
||||||
thread will be created for each goroutine, and <code>GOMAXPROCS</code> is
|
|
||||||
effectively equal to the number of running goroutines.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -1010,10 +1018,6 @@ documentation</a>.)
|
|||||||
Why does using <code>GOMAXPROCS</code> > 1 sometimes make my program
|
Why does using <code>GOMAXPROCS</code> > 1 sometimes make my program
|
||||||
slower?</h3>
|
slower?</h3>
|
||||||
|
|
||||||
<p>
|
|
||||||
(This is specific to the gc compilers. See above.)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
It depends on the nature of your program.
|
It depends on the nature of your program.
|
||||||
Programs that contain several goroutines that spend a lot of time
|
Programs that contain several goroutines that spend a lot of time
|
||||||
@ -1067,7 +1071,7 @@ This is almost never the desired behavior.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="closures_and_goroutines">
|
<h3 id="closures_and_goroutines">
|
||||||
Why am I confused by the way my closures behave as goroutines?</h3>
|
What happens with closures running as goroutines?</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Some confusion may arise when using closures with concurrency.
|
Some confusion may arise when using closures with concurrency.
|
||||||
@ -1076,29 +1080,30 @@ Consider the following program:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
func main() {
|
func main() {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
|
|
||||||
values := []string{ "a", "b", "c" }
|
values := []string{ "a", "b", "c" }
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
go func() {
|
go func() {
|
||||||
fmt.Println(v)
|
fmt.Println(v)
|
||||||
done <- true
|
done <- true
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for all goroutines to complete before exiting
|
// wait for all goroutines to complete before exiting
|
||||||
for _ = range values {
|
for _ = range values {
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
One might mistakenly expect to see <code>a, b, c</code> as the output.
|
One might mistakenly expect to see <code>a, b, c</code> as the output.
|
||||||
What you'll probably see instead is <code>c, c, c</code>. This is because
|
What you'll probably see instead is <code>c, c, c</code>. This is because
|
||||||
each closure shares the same variable <code>v</code>. Each closure prints the
|
each iteration of the loop uses the same instance of the variable <code>v</code>, so
|
||||||
value of <code>v</code> at the time <code>fmt.Println</code> is executed,
|
each closure shares that single variable. When the closure runs, it prints the
|
||||||
rather than the value of <code>v</code> when the goroutine was launched.
|
value of <code>v</code> at the time <code>fmt.Println</code> is executed,
|
||||||
|
but <code>v</code> may have been modified since the goroutine was launched.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -1107,12 +1112,12 @@ could modify the inner loop to read:
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
go func(<b>u</b> string) {
|
go func(<b>u</b> string) {
|
||||||
fmt.Println(<b>u</b>)
|
fmt.Println(<b>u</b>)
|
||||||
done <- true
|
done <- true
|
||||||
}(<b>v</b>)
|
}(<b>v</b>)
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -1133,9 +1138,9 @@ result:
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
if expr {
|
if expr {
|
||||||
n = trueVal
|
n = trueVal
|
||||||
} else {
|
} else {
|
||||||
n = falseVal
|
n = falseVal
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -1327,9 +1332,9 @@ import "unused"
|
|||||||
var _ = unused.Item // TODO: Delete before committing!
|
var _ = unused.Item // TODO: Delete before committing!
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
debugData := debug.Profile()
|
debugData := debug.Profile()
|
||||||
_ = debugData // Used only during debugging.
|
_ = debugData // Used only during debugging.
|
||||||
....
|
....
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -1343,10 +1348,12 @@ One of Go's design goals is to approach the performance of C for comparable
|
|||||||
programs, yet on some benchmarks it does quite poorly, including several
|
programs, yet on some benchmarks it does quite poorly, including several
|
||||||
in <a href="/test/bench/">test/bench</a>. The slowest depend on libraries
|
in <a href="/test/bench/">test/bench</a>. The slowest depend on libraries
|
||||||
for which versions of comparable performance are not available in Go.
|
for which versions of comparable performance are not available in Go.
|
||||||
For instance, pidigits depends on a multi-precision math package, and the C
|
For instance, <a href="/test/bench/shootout/pidigits.go">pidigits.go</a>
|
||||||
|
depends on a multi-precision math package, and the C
|
||||||
versions, unlike Go's, use <a href="http://gmplib.org/">GMP</a> (which is
|
versions, unlike Go's, use <a href="http://gmplib.org/">GMP</a> (which is
|
||||||
written in optimized assembler).
|
written in optimized assembler).
|
||||||
Benchmarks that depend on regular expressions (regex-dna, for instance) are
|
Benchmarks that depend on regular expressions
|
||||||
|
(<a href="/test/bench/shootout/regex-dna.go">regex-dna.go</a>, for instance) are
|
||||||
essentially comparing Go's native <a href="/pkg/regexp">regexp package</a> to
|
essentially comparing Go's native <a href="/pkg/regexp">regexp package</a> to
|
||||||
mature, highly optimized regular expression libraries like PCRE.
|
mature, highly optimized regular expression libraries like PCRE.
|
||||||
</p>
|
</p>
|
||||||
@ -1354,7 +1361,8 @@ mature, highly optimized regular expression libraries like PCRE.
|
|||||||
<p>
|
<p>
|
||||||
Benchmark games are won by extensive tuning and the Go versions of most
|
Benchmark games are won by extensive tuning and the Go versions of most
|
||||||
of the benchmarks need attention. If you measure comparable C
|
of the benchmarks need attention. If you measure comparable C
|
||||||
and Go programs (reverse-complement is one example), you'll see the two
|
and Go programs
|
||||||
|
(<a href="/test/bench/shootout/reverse-complement.go">reverse-complement.go</a> is one example), you'll see the two
|
||||||
languages are much closer in raw performance than this suite would
|
languages are much closer in raw performance than this suite would
|
||||||
indicate.
|
indicate.
|
||||||
</p>
|
</p>
|
||||||
@ -1362,8 +1370,8 @@ indicate.
|
|||||||
<p>
|
<p>
|
||||||
Still, there is room for improvement. The compilers are good but could be
|
Still, there is room for improvement. The compilers are good but could be
|
||||||
better, many libraries need major performance work, and the garbage collector
|
better, many libraries need major performance work, and the garbage collector
|
||||||
isn't fast enough yet (even if it were, taking care not to generate unnecessary
|
isn't fast enough yet. (Even if it were, taking care not to generate unnecessary
|
||||||
garbage can have a huge effect).
|
garbage can have a huge effect.)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -1398,13 +1406,13 @@ prefix <code>*</code> for pointers is an exception that proves the rule). In C,
|
|||||||
the declaration
|
the declaration
|
||||||
</p>
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
int* a, b;
|
int* a, b;
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
declares <code>a</code> to be a pointer but not <code>b</code>; in Go
|
declares <code>a</code> to be a pointer but not <code>b</code>; in Go
|
||||||
</p>
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
var a, b *int
|
var a, b *int
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
declares both to be pointers. This is clearer and more regular.
|
declares both to be pointers. This is clearer and more regular.
|
||||||
@ -1412,11 +1420,11 @@ Also, the <code>:=</code> short declaration form argues that a full variable
|
|||||||
declaration should present the same order as <code>:=</code> so
|
declaration should present the same order as <code>:=</code> so
|
||||||
</p>
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
var a uint64 = 1
|
var a uint64 = 1
|
||||||
</pre>
|
</pre>
|
||||||
has the same effect as
|
has the same effect as
|
||||||
<pre>
|
<pre>
|
||||||
a := uint64(1)
|
a := uint64(1)
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
Parsing is also simplified by having a distinct grammar for types that
|
Parsing is also simplified by having a distinct grammar for types that
|
||||||
@ -1495,8 +1503,7 @@ memory management. We feel it's critical to eliminate that
|
|||||||
programmer overhead, and advances in garbage collection
|
programmer overhead, and advances in garbage collection
|
||||||
technology in the last few years give us confidence that we can
|
technology in the last few years give us confidence that we can
|
||||||
implement it with low enough overhead and no significant
|
implement it with low enough overhead and no significant
|
||||||
latency. (The current implementation is a plain mark-and-sweep
|
latency.
|
||||||
collector but a replacement is in the works.)
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -1515,6 +1522,11 @@ Finally, concurrency aside, garbage collection makes interfaces
|
|||||||
simpler because they don't need to specify how memory is managed across them.
|
simpler because they don't need to specify how memory is managed across them.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The current implementation is a parallel mark-and-sweep
|
||||||
|
collector but a future version might take a different approach.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
On the topic of performance, keep in mind that Go gives the programmer
|
On the topic of performance, keep in mind that Go gives the programmer
|
||||||
considerable control over memory layout and allocation, much more than
|
considerable control over memory layout and allocation, much more than
|
||||||
|
Loading…
Reference in New Issue
Block a user