From: Rob Pike mixedCaps rather than underscores to write
multiword names.
+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:
+
+func CopyInBackground(src, dst chan Item) {
+ go func() { for { dst <- <-src } }()
+}
+
-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.
+In fact, semicolons can omitted at the end of any "StatementList" in the
+grammar, which includes things like cases in switch
+statements:
-length := Point{x, y}.Abs();
+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:
+
-// Prepare RPCMessage to send to server
-rpc := &RPCMessage {
- Version: 1,
- Header: &RPCHeader {
- Id: nextId(),
- Signature: sign(body),
- Method: method,
- },
- Body: body,
-};
+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:
+
-header, body, checksum := buf[0:20], buf[20:n-4], buf[n-4:n];
+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âthe unnecessary
+else is omitted.
+
+f, err := os.Open(name, os.O_RDONLY, 0);
+if err != nil {
+ return err;
+}
+codeUsing(f);
+
-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.
+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;
+ return err;
}
-codeUsing(f);
+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 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