diff options
Diffstat (limited to 'doc/effective_go.html')
-rw-r--r-- | doc/effective_go.html | 99 |
1 files changed, 61 insertions, 38 deletions
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 <code>godoc</code> does do is to display indented text in a fixed-width font, suitable for program snippets. The package comment for the -<a href="http://golang.org/pkg/fmt/"><code>fmt</code> package</a> uses this to good effect. +<a href="/pkg/fmt/"><code>fmt</code> package</a> uses this to good effect. </p> <p> @@ -288,7 +288,7 @@ var ( </pre> <p> -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. </p> @@ -350,7 +350,7 @@ not <code>encoding_base64</code> and not <code>encodingBase64</code>. </p> <p> -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 <code>import .</code> notation, which can simplify @@ -701,6 +701,7 @@ for _, value := range array { <p> The blank identifier has many uses, as described in <a href="#blank">a later section</a>. +</p> <p> For strings, the <code>range</code> 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) <code>rune</code> is Go terminology for a single Unicode code point. -See <a href="http://golang.org/ref/spec#Rune_literals">the language specification</a> +See <a href="/ref/spec#Rune_literals">the language specification</a> for details.) The loop </p> @@ -849,7 +850,7 @@ func Compare(a, b []byte) int { } </pre> -<h2 id="type_switch">Type switch</h2> +<h3 id="type_switch">Type switch</h3> <p> 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) </pre> <p> 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 -<code>b</code>, <i>slice</i> (here used as a verb) the buffer. +any. +To read into the first 32 bytes of a larger buffer +<code>buf</code>, <i>slice</i> (here used as a verb) the buffer. </p> <pre> 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: </p> <pre> @@ -2054,10 +2056,22 @@ We pass the address of a <code>ByteSlice</code> because only <code>*ByteSlice</code> satisfies <code>io.Writer</code>. 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. </p> + +<p> +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 <code>b</code> is addressable, so we can call +its <code>Write</code> method with just <code>b.Write</code>. The compiler +will rewrite that to <code>(&b).Write</code> for us. +</p> + <p> By the way, the idea of using <code>Write</code> on a slice of bytes is central to the implementation of <code>bytes.Buffer</code>. @@ -2173,6 +2187,7 @@ A one-case type switch would do, but so would a <em>type assertion</em>. 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 <code>type</code> keyword: +</p> <pre> value.(typeName) @@ -2463,6 +2478,8 @@ It has uses beyond those we've seen already. <p> The use of a blank identifier in a <code>for</code> <code>range</code> loop is a special case of a general situation: multiple assignment. +</p> + <p> 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. <p> A buffered channel can be used like a semaphore, for instance to limit throughput. In this example, incoming requests are passed -to <code>handle</code>, 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 <code>handle</code>, 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 <code>process</code>, -so during initialization we prime the channel by filling it to capacity. +simultaneous calls to <code>process</code>. </p> <pre> 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) { </pre> <p> -Because data synchronization occurs on a receive from a channel -(that is, the send "happens before" the receive; see -<a href="/ref/mem">The Go Memory Model</a>), -acquisition of the semaphore must be on a channel receive, not a send. +Once <code>MaxOutstanding</code> handlers are executing <code>process</code>, +any more will block trying to send into the filled channel buffer, +until one of the existing handlers finishes and receives from the buffer. </p> <p> @@ -2988,10 +2997,10 @@ Here's an obvious solution, but beware it has a bug we'll fix subsequently: <pre> func Serve(queue chan *Request) { for req := range queue { - <-sem + sem <- 1 go func() { process(req) // Buggy; see explanation below. - sem <- 1 + <-sem }() } }</pre> @@ -3009,10 +3018,10 @@ to the closure in the goroutine: <pre> func Serve(queue chan *Request) { for req := range queue { - <-sem + sem <- 1 go func(req *Request) { process(req) - sem <- 1 + <-sem }(req) } }</pre> @@ -3027,11 +3036,11 @@ name, as in this example: <pre> 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 }() } }</pre> @@ -3278,9 +3287,18 @@ the garbage collector for bookkeeping. <p> 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 <code>error</code>, +return value. +It is good style to use this feature to provide detailed error information. +For example, as we'll see, <code>os.Open</code> doesn't +just return a <code>nil</code> pointer on failure, it also returns an +error value that describes what went wrong. +</p> + +<p> +By convention, errors have type <code>error</code>, a simple built-in interface. </p> <pre> @@ -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, <code>os.Open</code> returns an <code>os.PathError</code>. +As mentioned, alongside the usual <code>*os.File</code> +return value, <code>os.Open</code> also returns an +error value. +If the file is opened successfully, the error will be <code>nil</code>, +but when there is a problem, it will hold an +<code>os.PathError</code>: </p> <pre> // PathError records an error and the operation and |