From 8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 19 Jun 2014 09:22:53 +0200 Subject: Imported Upstream version 1.3 --- doc/effective_go.html | 99 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 38 deletions(-) (limited to 'doc/effective_go.html') diff --git a/doc/effective_go.html b/doc/effective_go.html index f9199511a..25266d6ab 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -214,7 +214,7 @@ not be used. One adjustment godoc does do is to display indented text in a fixed-width font, suitable for program snippets. The package comment for the -fmt package uses this to good effect. +fmt package uses this to good effect.

@@ -288,7 +288,7 @@ var (

-Even for private names, grouping can also indicate relationships between items, +Grouping can also indicate relationships between items, such as the fact that a set of variables is protected by a mutex.

@@ -350,7 +350,7 @@ not encoding_base64 and not encodingBase64.

-The importer of a package will use the name to refer to its contents. +The importer of a package will use the name to refer to its contents, so exported names in the package can use that fact to avoid stutter. (Don't use the import . notation, which can simplify @@ -701,6 +701,7 @@ for _, value := range array {

The blank identifier has many uses, as described in a later section. +

For strings, the range does more work for you, breaking out individual @@ -709,7 +710,7 @@ Erroneous encodings consume one byte and produce the replacement rune U+FFFD. (The name (with associated builtin type) rune is Go terminology for a single Unicode code point. -See the language specification +See the language specification for details.) The loop

@@ -849,7 +850,7 @@ func Compare(a, b []byte) int { } -

Type switch

+

Type switch

A switch can also be used to discover the dynamic type of an interface @@ -1385,8 +1386,9 @@ func (file *File) Read(buf []byte) (n int, err error)

The method returns the number of bytes read and an error value, if -any. To read into the first 32 bytes of a larger buffer -b, slice (here used as a verb) the buffer. +any. +To read into the first 32 bytes of a larger buffer +buf, slice (here used as a verb) the buffer.

     n, err := f.Read(buf[0:32])
@@ -1487,7 +1489,7 @@ If the slices might grow or shrink, they should be allocated independently
 to avoid overwriting the next line; if not, it can be more efficient to construct
 the object with a single allocation.
 For reference, here are sketches of the two methods.
-First, a line a time:
+First, a line at a time:
 

@@ -2054,10 +2056,22 @@ We pass the address of a ByteSlice
 because only *ByteSlice satisfies io.Writer.
 The rule about pointers vs. values for receivers is that value methods
 can be invoked on pointers and values, but pointer methods can only be
-invoked on pointers.  This is because pointer methods can modify the
-receiver; invoking them on a copy of the value would cause those
-modifications to be discarded.
+invoked on pointers.
 

+ +

+This rule arises because pointer methods can modify the receiver; invoking +them on a value would cause the method to receive a copy of the value, so +any modifications would be discarded. +The language therefore disallows this mistake. +There is a handy exception, though. When the value is addressable, the +language takes care of the common case of invoking a pointer method on a +value by inserting the address operator automatically. +In our example, the variable b is addressable, so we can call +its Write method with just b.Write. The compiler +will rewrite that to (&b).Write for us. +

+

By the way, the idea of using Write on a slice of bytes is central to the implementation of bytes.Buffer. @@ -2173,6 +2187,7 @@ A one-case type switch would do, but so would a type assertion. A type assertion takes an interface value and extracts from it a value of the specified explicit type. The syntax borrows from the clause opening a type switch, but with an explicit type rather than the type keyword: +

 value.(typeName)
@@ -2463,6 +2478,8 @@ It has uses beyond those we've seen already.
 

The use of a blank identifier in a for range loop is a special case of a general situation: multiple assignment. +

+

If an assignment requires multiple values on the left side, but one of the values will not be used by the program, @@ -2937,26 +2954,19 @@ means waiting until some receiver has retrieved a value.

A buffered channel can be used like a semaphore, for instance to limit throughput. In this example, incoming requests are passed -to handle, which receives a value from the channel, processes -the request, and then sends a value back to the channel -to ready the "semaphore" for the next consumer. +to handle, which sends a value into the channel, processes +the request, and then receives a value from the channel +to ready the “semaphore” for the next consumer. The capacity of the channel buffer limits the number of -simultaneous calls to process, -so during initialization we prime the channel by filling it to capacity. +simultaneous calls to process.

 var sem = make(chan int, MaxOutstanding)
 
 func handle(r *Request) {
-    <-sem          // Wait for active queue to drain.
-    process(r)     // May take a long time.
-    sem <- 1       // Done; enable next request to run.
-}
-
-func init() {
-    for i := 0; i < MaxOutstanding; i++ {
-        sem <- 1
-    }
+    sem <- 1    // Wait for active queue to drain.
+    process(r)  // May take a long time.
+    <-sem       // Done; enable next request to run.
 }
 
 func Serve(queue chan *Request) {
@@ -2968,10 +2978,9 @@ func Serve(queue chan *Request) {
 

-Because data synchronization occurs on a receive from a channel -(that is, the send "happens before" the receive; see -The Go Memory Model), -acquisition of the semaphore must be on a channel receive, not a send. +Once MaxOutstanding handlers are executing process, +any more will block trying to send into the filled channel buffer, +until one of the existing handlers finishes and receives from the buffer.

@@ -2988,10 +2997,10 @@ Here's an obvious solution, but beware it has a bug we'll fix subsequently:

 func Serve(queue chan *Request) {
     for req := range queue {
-        <-sem
+        sem <- 1
         go func() {
             process(req) // Buggy; see explanation below.
-            sem <- 1
+            <-sem
         }()
     }
 }
@@ -3009,10 +3018,10 @@ to the closure in the goroutine:
 func Serve(queue chan *Request) {
     for req := range queue {
-        <-sem
+        sem <- 1
         go func(req *Request) {
             process(req)
-            sem <- 1
+            <-sem
         }(req)
     }
 }
@@ -3027,11 +3036,11 @@ name, as in this example:
 func Serve(queue chan *Request) {
     for req := range queue {
-        <-sem
         req := req // Create new instance of req for the goroutine.
+        sem <- 1
         go func() {
             process(req)
-            sem <- 1
+            <-sem
         }()
     }
 }
@@ -3278,9 +3287,18 @@ the garbage collector for bookkeeping.

Library routines must often return some sort of error indication to -the caller. As mentioned earlier, Go's multivalue return makes it +the caller. +As mentioned earlier, Go's multivalue return makes it easy to return a detailed error description alongside the normal -return value. By convention, errors have type error, +return value. +It is good style to use this feature to provide detailed error information. +For example, as we'll see, os.Open doesn't +just return a nil pointer on failure, it also returns an +error value that describes what went wrong. +

+ +

+By convention, errors have type error, a simple built-in interface.

@@ -3292,7 +3310,12 @@ type error interface {
 A library writer is free to implement this interface with a
 richer model under the covers, making it possible not only
 to see the error but also to provide some context.
-For example, os.Open returns an os.PathError.
+As mentioned, alongside the usual *os.File
+return value, os.Open also returns an
+error value.
+If the file is opened successfully, the error will be nil,
+but when there is a problem, it will hold an
+os.PathError:
 

 // PathError records an error and the operation and
-- 
cgit v1.2.3