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.

- -

Idioms

- -

Allocate using literals

+

Semicolons

-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,
-};
-
- -

Use parallel assignment to slice a buffer

- -
-header, body, checksum := buf[0:20], buf[20:n-4], buf[n-4:n];
-
- -

Control Flow

- -

Omit needless else bodies

-

-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. +

+ +

Control structures

+ +

+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. +

+ +

If

+ +

+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);
+
+ +

Switch

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:

-go/src/pkg/http/url.go:
 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 os.Error, not bool

@@ -498,30 +616,6 @@ Even if there is only one failure mode now, there may be more later.

-

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 of os.Error should