diff --git a/doc/effective_go.html b/doc/effective_go.html
index b7b948d8e53..b79f2a7a5c4 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -349,71 +349,150 @@ or mixedCaps
rather than underscores to write
multiword names.
-A struct literal is an expression that creates a
-new instance each time it is evaluated. The address of such
-an expression points to a fresh instance each time.
-Use such expressions to avoid the repetition of filling
-out a data structure.
+Go needs fewer semicolons between statements than do other C variants.
+Semicolons are never required at the top level.
+Also they are separators, not terminators, so they
+can be left off the last element of a statement or declaration list,
+a convenience
+for one-line funcs
and the like:
-length := Point{x, y}.Abs(); +func CopyInBackground(src, dst chan Item) { + go func() { for { dst <- <-src } }() +}-
-// Prepare RPCMessage to send to server -rpc := &RPCMessage { - Version: 1, - Header: &RPCHeader { - Id: nextId(), - Signature: sign(body), - Method: method, - }, - Body: body, -}; -- -
-header, body, checksum := buf[0:20], buf[20:n-4], buf[n-4:n]; -- -
-When an if
statement doesn't flow into the next statement—that is,
+In fact, semicolons can omitted at the end of any "StatementList" in the
+grammar, which includes things like cases in switch
+statements:
+
+switch { +case a < b: + return -1 +case a == b: + return 0 +case a > b: + return 1 +} + ++ +
+The grammar admits an empty statement after any statement list, which
+means a terminal semicolon is always OK. As a result,
+it's fine to put semicolons everywhere you'd put them in a
+C program—they would be fine after those return statements,
+for instance—but they can often be omitted.
+By convention, they're always left off top-level declarations (for
+instance, they don't appear after the closing brace of struct
+declarations, or of funcs
for that matter)
+and often left off one-liners. But within functions, place them
+as you see fit.
+
+The control structures of Go are related to those of C but different
+in important ways.
+There is no do
or while
loop, only a
+slightly generalized
+for
;
+switch
is more flexible;
+if
and switch
accept an optional
+initialization statement like that of for
;
+and there are new control structures including a type switch and a
+multiway communications multiplexer, select
.
+The syntax is also slightly different: parentheses are not part of the syntax
+and the bodies must always be brace-delimited.
+
+In Go a simple if
looks like this:
+
+if x > 0 { + return y +} ++ +
+Mandatory braces encourage writing simple if
statements
+on multiple lines. It's good style to do so anyway,
+especially when the body contains a control statement such as a
+return
or break
.
+
+Since if
and switch
accept an initialization
+statement, it's common to see one used to set up a local variable:
+
+if err := file.Chmod(0664); err != nil { + log.Stderr(err) +} ++ +
+In the Go libraries, you'll find that
+when an if
statement doesn't flow into the next statement—that is,
the body ends in break
, continue
,
-goto
, or return
—omit the else
.
+goto
, or return
—the unnecessary
+else
is omitted.
f, err := os.Open(name, os.O_RDONLY, 0); if err != nil { - return err; + return err; } codeUsing(f);+
+This is a example of a common situation where code must analyze a
+sequence of error possibilities. The code reads well if the
+successful flow of control runs down the page, eliminating error cases
+as they arise. Since error cases tend to end in return
+statements, the resulting code needs no else
statements:
+
+f, err := os.Open(name, os.O_RDONLY, 0); +if err != nil { + return err; +} +d, err := f.Stat(); +if err != nil { + return err; +} +codeUsing(f, d); ++ +
Go's switch
is more general than C's.
-When an if
-else
-if
-else
-chain has three or more bodies,
-or an if
condition has a long list of alternatives,
-it will be clearer if rewritten as a switch
.
+The expressions need not be constants or even integers,
+the cases are evaluated top to bottom until a match is found,
+and if the switch
has no expression it switches on
+true
.
+It's therefore possible—and idiomatic—to write an
+if
-else
-if
-else
+chain as a switch
:
func unhex(c byte) byte { switch { @@ -428,7 +507,9 @@ func unhex(c byte) byte { }-go/src/pkg/http/url.go: +
+There is no automatic fall through, but cases can be presented +in comma-separated lists:
func shouldEscape(c byte) bool { switch c { @@ -439,11 +520,13 @@ func shouldEscape(c byte) bool { }-go/src/pkg/bytes/bytes.go: +
+Here's a comparison routine for byte arrays that uses two
+switch
statements:
// Compare returns an integer comparing the two byte arrays // lexicographically. -// The result will be 0 if a==b, -1 if a < b, and +1 if a > b +// The result will be 0 if a == b, -1 if a < b, and +1 if a > b func Compare(a, b []byte) int { for i := 0; i < len(a) && i < len(b); i++ { switch { @@ -486,6 +569,41 @@ do so directly. There is no need to pass a pointer to a return value. +Idioms
+ +Allocate using literals
+ ++A struct literal is an expression that creates a +new instance each time it is evaluated. The address of such +an expression points to a fresh instance each time. +Use such expressions to avoid the repetition of filling +out a data structure. +
+ ++length := Point{x, y}.Abs(); ++ ++// Prepare RPCMessage to send to server +rpc := &RPCMessage { + Version: 1, + Header: &RPCHeader { + Id: nextId(), + Signature: sign(body), + Method: method, + }, + Body: body, +}; ++ +Use parallel assignment to slice a buffer
+ ++header, body, checksum := buf[0:20], buf[20:n-4], buf[n-4:n]; ++Errors
Return
@@ -498,30 +616,6 @@ Even if there is only one failure mode now, there may be more later. -os.Error
, notbool
Handle errors first
- --Error cases tend to be simpler than non-error cases, -and it helps readability when the non-error flow -of control is always down the page. -Also, error cases tend to end in
- -return
statements, -so that there is no need for an explicit else. --if len(name) == 0 { - return os.EINVAL; -} -if IsDir(name) { - return os.EISDIR; -} -f, err := os.Open(name, os.O_RDONLY, 0); -if err != nil { - return err; -} -codeUsing(f); --Return structured errors
Implementations ofos.Error
should