| |
| <h2 id="introduction">Introduction</h2> |
| |
| <p> |
| Go is a new language. Although it's in the C family |
| it has some unusual properties that make effective Go programs |
| different in character from programs in existing languages. |
| A straightforward translation of a C++ or Java program into Go |
| is unlikely to produce a satisfactory result—Java programs |
| are written in Java, not Go. |
| On the other hand, thinking about the problem from a Go |
| perspective could produce a successful but quite different |
| program. |
| In other words, |
| to write Go well, it's important to understand its properties |
| and idioms. |
| It's also important to know the established conventions for |
| programming in Go, such as naming, formatting, program |
| construction, and so on, so that programs you write |
| will be easy for other Go programmers to understand. |
| </p> |
| |
| <p> |
| This document gives tips for writing clear, idiomatic Go code. |
| It augments the <a href="go_spec.html">language specification</a> |
| and the <a href="go_tutorial.html">tutorial</a>, both of which you |
| should read first. |
| </p> |
| |
| <h3 id="read">Examples</h3> |
| |
| <p> |
| The <a href="/src/pkg/">Go package sources</a> |
| are intended to serve not |
| only as the core library but also as examples of how to |
| use the language. |
| If you have a question about how to approach a problem or how something |
| might be implemented they can provide answers, ideas and |
| background. |
| </p> |
| |
| |
| <h2 id="formatting">Formatting</h2> |
| |
| <p> |
| Formatting issues are the most contentious |
| but the least consequential. |
| People can adapt to different formatting styles |
| but it's better if they don't have to, and |
| less time is devoted to the topic |
| if everyone adheres to the same style. |
| The problem is how to approach this Utopia without a long |
| prescriptive style guide. |
| </p> |
| |
| <p> |
| With Go we take an unusual |
| approach and let the machine |
| take care of most formatting issues. |
| A program, <code>gofmt</code>, reads a Go program |
| and emits the source in a standard style of indentation |
| and vertical alignment, retaining and if necessary |
| reformatting comments. |
| If you want to know how to handle some new layout |
| situation, run <code>gofmt</code>; if the answer doesn't |
| seem right, fix the program (or file a bug), don't work around it. |
| </p> |
| |
| <p> |
| As an example, there's no need to spend time lining up |
| the comments on the fields of a structure. |
| <code>Gofmt</code> will do that for you. Given the |
| declaration |
| </p> |
| |
| <pre> |
| type T struct { |
| name string; // name of the object |
| value int; // its value |
| } |
| </pre> |
| |
| <p> |
| <code>gofmt</code> will make the columns line up: |
| </p> |
| |
| <pre> |
| type T struct { |
| name string; // name of the object |
| value int; // its value |
| } |
| </pre> |
| |
| <p> |
| All code in the libraries has been formatted with <code>gofmt</code>. |
| <font color=red>TODO</font> |
| </p> |
| |
| |
| <p> |
| Some formatting details remain. Very briefly: |
| </p> |
| |
| <dl> |
| <dt>Indentation</dt> |
| <dd>We use tabs for indentation and <code>gofmt</code> emits them by default. |
| Use spaces if you must. |
| </dd> |
| <dt>Line length</dt> |
| <dd> |
| Go has no line length limit. Don't worry about overflowing a punched card. |
| If a line feels too long, wrap it and indent with an extra tab. |
| </dd> |
| <dt>Parentheses</dt> |
| <dd> |
| Go needs fewer parentheses: control structures (<code>if</code>, |
| <code>for</code>, <code>switch</code>) do not have parentheses in |
| their syntax. |
| Also, the operator precedence hierarchy is shorter and clearer, so |
| <pre> |
| x<<8 + y<<16 |
| </pre> |
| means what the spacing implies. |
| </dd> |
| </dl> |
| |
| <h2>Commentary</h2> |
| |
| <p> |
| Go provides C-style <code>/* */</code> block comments |
| and C++-style <code>//</code> line comments. |
| Line comments are the norm; |
| block comments appear mostly as package comments and |
| are also useful to disable large swaths of code. |
| </p> |
| |
| <p> |
| The program—and web server—<code>godoc</code> processes |
| Go source files to extract documentation about the contents of the |
| package. |
| Comments that appear before top-level declarations, with no intervening newlines, |
| are extracted along with the declaration to serve as explanatory text for the item. |
| The nature and style of these comments determines the |
| quality of the documentation <code>godoc</code> produces. |
| </p> |
| |
| <p> |
| Every package should have a <i>package comment</i>, a block |
| comment preceding the package clause. |
| For multi-file packages, the package comment only needs to be |
| present in one file, and any one will do. |
| The package comment should introduce the package and |
| provide information relevant to the package as a whole. |
| It will appear first on the <code>godoc</code> page and |
| should set up the detailed documentation that follows. |
| </p> |
| |
| <pre> |
| /* |
| The regexp package implements a simple library for |
| regular expressions. |
| |
| The syntax of the regular expressions accepted is: |
| |
| regexp: |
| concatenation { '|' concatenation } |
| concatenation: |
| { closure } |
| closure: |
| term [ '*' | '+' | '?' ] |
| term: |
| '^' |
| '$' |
| '.' |
| character |
| '[' [ '^' ] character-ranges ']' |
| '(' regexp ')' |
| */ |
| package regexp |
| </pre> |
| |
| <p> |
| If the package is simple, the package comment can be brief. |
| </p> |
| |
| <pre> |
| // The path package implements utility routines for |
| // manipulating slash-separated filename paths. |
| </pre> |
| |
| <p> |
| Comments do not need extra formatting such as banners of stars. |
| The generated output may not even be presented in a fixed-width font, so don't depend |
| on spacing for alignment—<code>godoc</code>, like <code>gofmt</code>, |
| takes care of that. |
| Finally, the comments are uninterpreted plain text, so HTML and other |
| annotations such as <code>_this_</code> will reproduce <i>verbatim</i> and should |
| not be used. |
| </p> |
| |
| <p> |
| Inside a package, any comment immediately preceding a top-level declaration |
| serves as a <i>doc comment</i> for that declaration. |
| Every exported (capitalized) name in a program should |
| have a doc comment. |
| </p> |
| |
| <p> |
| Doc comments work best as complete English sentences, which allow |
| a wide variety of automated presentations. |
| The first sentence should be a one-sentence summary that |
| starts with the name being declared: |
| </p> |
| |
| <pre> |
| // Compile parses a regular expression and returns, if successful, a Regexp |
| // object that can be used to match against text. |
| func Compile(str string) (regexp *Regexp, error os.Error) { |
| </pre> |
| |
| <p> |
| Go's declaration syntax allows grouping of declarations. |
| A single doc comment can introduce a group of related constants or variables. |
| Since the whole declaration is presented, such a comment can often be perfunctory. |
| </p> |
| |
| <pre> |
| // Error codes returned by failures to parse an expression. |
| var ( |
| ErrInternal = os.NewError("internal error"); |
| ErrUnmatchedLpar = os.NewError("unmatched '('"); |
| ErrUnmatchedRpar = os.NewError("unmatched ')'"); |
| ... |
| ) |
| </pre> |
| |
| <p> |
| Even for private names, grouping can also indicate relationships between items, |
| such as the fact that a set of variables is controlled by a mutex. |
| </p> |
| |
| <pre> |
| var ( |
| countLock sync.Mutex; |
| inputCount uint32; |
| outputCount uint32; |
| errorCount uint32; |
| ) |
| </pre> |
| |
| <h2 id="names">Names</h2> |
| |
| <p> |
| Names are as important in Go as in any other language. |
| In some cases they even have semantic effect: for instance, |
| the visibility of a name outside a package is determined by whether its |
| first character is an upper case letter, |
| while methods are looked up by name alone (although the type must match too). |
| It's therefore worth spending a little time talking about naming conventions |
| in Go programs. |
| </p> |
| |
| |
| <h3 id="package-names">Package names</h3> |
| |
| <p> |
| When a package is imported, the package name becomes an accessor for the |
| contents. After |
| </p> |
| |
| <pre> |
| import "bytes" |
| </pre> |
| |
| <p> |
| the importing package can talk about <code>bytes.Buffer</code>. It's |
| helpful if everyone using the package can use the same name to refer to |
| its contents, which implies that the package name should be good: |
| short, concise, evocative. By convention, packages are given |
| lower case, single-word names; there should be no need for underscores |
| or mixedCaps. |
| Err on the side of brevity, since everyone using your |
| package will be typing that name. |
| And don't worry about collisions <i>a priori</i>. |
| The package name is only the default name for imports; it need not be unique |
| across all source code, and in the rare case of a collision the |
| importing package can choose a different name to use locally. |
| </p> |
| |
| <p> |
| Another convention is that the package name is the base name of |
| its source directory; |
| the package in <code>src/pkg/container/vector</code> |
| is installed as <code>"container/vector"</code> but has name <code>vector</code>, |
| not <code>container_vector</code> and not <code>containerVector</code>. |
| </p> |
| |
| <p> |
| The importer of a package will use the name to refer to its contents |
| (the <code>import .</code> notation is intended mostly for tests and other |
| unusual situations), and exported names in the package can use that fact |
| to avoid stutter. |
| For instance, the buffered reader type in the <code>bufio</code> package is called <code>Reader</code>, |
| not <code>BufReader</code>, because users see it as <code>bufio.Reader</code>, |
| which is a clear, concise name. |
| Moreover, |
| because imported entities are always addressed with their package name, <code>bufio.Reader</code> |
| does not conflict with <code>io.Reader</code>. |
| Use the package structure to help you choose good names. |
| </p> |
| |
| <p> |
| Another short example is <code>once.Do</code>; |
| <code>once.Do(setup)</code> reads well and would not be improved by |
| writing <code>once.DoOrWaitUntilDone(setup)</code>. |
| Long names don't automatically make things more readable. |
| If the name represents something intricate or subtle, it's usually better |
| to write a helpful doc comment than to attempt to put all the information |
| into the name. |
| </p> |
| |
| <h3 id="interface-names">Interface names</h3> |
| |
| <p> |
| By convention, one-method interfaces are named by |
| the method name plus the -er suffix: <code>Reader</code>, |
| <code>Writer</code>, <code>Formatter</code> etc. |
| </p> |
| |
| <p> |
| There are a number of such names and it's productive to honor them and the function |
| names they capture. |
| <code>Read</code>, <code>Write</code>, <code>Close</code>, <code>Flush</code>, |
| <code>String</code> and so on have |
| canonical signatures and meanings. To avoid confusion, |
| don't give your method one of those names unless it |
| has the same signature and meaning. |
| Conversely, if your type implements a method with the |
| same meaning as a method on a well-known type, |
| give it the same name and signature; |
| call your string-converter method <code>String</code> not <code>ToString</code>. |
| </p> |
| |
| <h3 id="mixed-caps">MixedCaps</h3> |
| |
| <p> |
| Finally, the convention in Go is to used <code>MixedCaps</code> |
| or <code>mixedCaps</code> rather than underscores to write |
| multiword names. |
| </p> |
| |
| <h2 id="semicolons">Semicolons</h2> |
| |
| <p> |
| 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 <code>funcs</code> and the like: |
| </p> |
| |
| <pre> |
| func CopyInBackground(dst, src chan Item) { |
| go func() { for { dst <- <-src } }() |
| } |
| </pre> |
| |
| <p> |
| In fact, semicolons can omitted at the end of any "StatementList" in the |
| grammar, which includes things like cases in <code>switch</code> |
| statements: |
| </p> |
| |
| <pre> |
| switch { |
| case a < b: |
| return -1 |
| case a == b: |
| return 0 |
| case a > b: |
| return 1 |
| } |
| |
| </pre> |
| |
| <p> |
| The grammar accepts 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 <code>struct</code> |
| declarations, or of <code>funcs</code> for that matter) |
| and often left off one-liners. But within functions, place them |
| as you see fit. |
| </p> |
| |
| <h2 id="control-structures">Control structures</h2> |
| |
| <p> |
| The control structures of Go are related to those of C but different |
| in important ways. |
| There is no <code>do</code> or <code>while</code> loop, only a |
| slightly generalized |
| <code>for</code>; |
| <code>switch</code> is more flexible; |
| <code>if</code> and <code>switch</code> accept an optional |
| initialization statement like that of <code>for</code>; |
| and there are new control structures including a type switch and a |
| multiway communications multiplexer, <code>select</code>. |
| The syntax is also slightly different: parentheses are not part of the syntax |
| and the bodies must always be brace-delimited. |
| </p> |
| |
| <h3 id="if">If</h3> |
| |
| <p> |
| In Go a simple <code>if</code> looks like this: |
| </p> |
| <pre> |
| if x > 0 { |
| return y |
| } |
| </pre> |
| |
| <p> |
| Mandatory braces encourage writing simple <code>if</code> statements |
| on multiple lines. It's good style to do so anyway, |
| especially when the body contains a control statement such as a |
| <code>return</code> or <code>break</code>. |
| </p> |
| |
| <p> |
| Since <code>if</code> and <code>switch</code> accept an initialization |
| statement, it's common to see one used to set up a local variable: |
| </p> |
| |
| <pre> |
| if err := file.Chmod(0664); err != nil { |
| log.Stderr(err) |
| } |
| </pre> |
| |
| <p id="else"> |
| In the Go libraries, you'll find that |
| when an <code>if</code> statement doesn't flow into the next statement—that is, |
| the body ends in <code>break</code>, <code>continue</code>, |
| <code>goto</code>, or <code>return</code>—the unnecessary |
| <code>else</code> is omitted. |
| </p> |
| |
| <pre> |
| f, err := os.Open(name, os.O_RDONLY, 0); |
| if err != nil { |
| return err; |
| } |
| codeUsing(f); |
| </pre> |
| |
| <p> |
| 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 <code>return</code> |
| statements, the resulting code needs no <code>else</code> statements: |
| </p> |
| |
| <pre> |
| 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); |
| </pre> |
| |
| |
| <h3 id="for">For</h3> |
| |
| <p> |
| The Go <code>for</code> loop is similar to—but not the same as—C's. |
| It unifies <code>for</code> |
| and <code>while</code> and there is no <code>do-while</code>. |
| There are three forms, only one of which has semicolons: |
| </p> |
| <pre> |
| // Like a C for |
| for init; condition; post { } |
| |
| // Like a C while |
| for condition { } |
| |
| // Like a C for(;;) |
| for { } |
| </pre> |
| |
| <p> |
| Short declarations make it easy to declare the index variable right in the loop: |
| </p> |
| <pre> |
| sum := 0; |
| for i := 0; i < 10; i++ { |
| sum += i |
| } |
| </pre> |
| |
| <p> |
| If you're looping over an array, slice, string, or map a <code>range</code> clause can set |
| it all up for you: |
| </p> |
| <pre> |
| var m map[string] int; |
| sum := 0; |
| for key, value := range m { // key is unused; could call it '_' |
| sum += value |
| } |
| </pre> |
| |
| <p> |
| For strings, the <code>range</code> does more of the work for you, breaking out individual |
| characters by parsing the UTF-8 (erroneous encodings consume one byte and produce the |
| replacement rune U+FFFD). The loop |
| </p> |
| <pre> |
| for pos, char := range "日本語" { |
| fmt.Printf("character %c starts at byte position %d\n", char, pos) |
| } |
| </pre> |
| <p> |
| prints |
| </p> |
| <pre> |
| character 日 starts at byte position 0 |
| character 本 starts at byte position 3 |
| character 語 starts at byte position 6 |
| </pre> |
| |
| <p> |
| Finally, since Go has no comma operator and <code>++</code> and <code>--</code> |
| are statements not expressions, if you want to run multiple variables in a <code>for</code> |
| you should use parallel assignment: |
| </p> |
| <pre> |
| // Reverse a |
| for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 { |
| a[i], a[j] = a[j], a[i] |
| } |
| </pre> |
| |
| <h3 id="switch">Switch</h3> |
| |
| <p> |
| Go's <code>switch</code> is more general than C's. |
| The expressions need not be constants or even integers, |
| the cases are evaluated top to bottom until a match is found, |
| and if the <code>switch</code> has no expression it switches on |
| <code>true</code>. |
| It's therefore possible—and idiomatic—to write an |
| <code>if</code>-<code>else</code>-<code>if</code>-<code>else</code> |
| chain as a <code>switch</code>: |
| </p> |
| |
| <pre> |
| func unhex(c byte) byte { |
| switch { |
| case '0' <= c && c <= '9': |
| return c - '0' |
| case 'a' <= c && c <= 'f': |
| return c - 'a' + 10 |
| case 'A' <= c && c <= 'F': |
| return c - 'A' + 10 |
| } |
| return 0 |
| } |
| </pre> |
| |
| <p> |
| There is no automatic fall through, but cases can be presented |
| in comma-separated lists: |
| <pre> |
| func shouldEscape(c byte) bool { |
| switch c { |
| case ' ', '?', '&', '=', '#', '+', '%': |
| return true |
| } |
| return false |
| } |
| </pre> |
| |
| <p> |
| Here's a comparison routine for byte arrays that uses two |
| <code>switch</code> statements: |
| <pre> |
| // 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 |
| func Compare(a, b []byte) int { |
| for i := 0; i < len(a) && i < len(b); i++ { |
| switch { |
| case a[i] > b[i]: |
| return 1 |
| case a[i] < b[i]: |
| return -1 |
| } |
| } |
| switch { |
| case len(a) < len(b): |
| return -1 |
| case len(a) > len(b): |
| return 1 |
| } |
| return 0 |
| } |
| </pre> |
| |
| <h2 id="functions">Functions</h2> |
| |
| <h3 id="multiple-returns">Multiple return values</h3> |
| |
| <p> |
| One of Go's unusual properties is that functions and methods |
| can return multiple values. This feature can be used to |
| improve on a couple of clumsy idioms in C program: in-band |
| error returns (<code>-1</code> for <code>EOF</code> for example) |
| and modifying an argument. |
| </p> |
| |
| <p> |
| In C, a write error is signaled by a negative byte count with the |
| error code secreted away in a volatile location. |
| In Go, <code>Write</code> |
| can return a byte count <i>and</i> an error: "Yes, you wrote some |
| bytes but not all of them because you filled the device". |
| The signature of <code>*File.Write</code> in package <code>os</code> is: |
| </p> |
| |
| <pre> |
| func (file *File) Write(b []byte) (n int, err Error) |
| </pre> |
| |
| <p> |
| and as the documentation says, it returns the number of bytes |
| written and a non-nil <code>Error</code> when <code>n</code> |
| <code>!=</code> <code>len(b)</code>. |
| This is a common style; see the section on error handling for more examples. |
| </p> |
| |
| <p> |
| A similar approach obviates the need to pass a pointer to a return |
| value to overwrite an argument. Here's a simple-minded function to |
| grab a number from a position in a byte array, returning the number |
| and the next position. |
| </p> |
| |
| <pre> |
| func nextInt(b []byte, i int) (int, int) { |
| for ; i < len(b) && !isDigit(b[i]); i++ { |
| } |
| x := 0; |
| for ; i < len(b) && isDigit(b[i]); i++ { |
| x = x*10 + int(b[i])-'0' |
| } |
| return x, i; |
| } |
| </pre> |
| |
| <p> |
| You could use it to scan the numbers in an input array <code>a</code> like this: |
| </p> |
| |
| <pre> |
| for i := 0; i < len(a); { |
| x, i = nextInt(a, i); |
| fmt.Println(x); |
| } |
| </pre> |
| |
| <h3 id="named-results">Named result parameters</h3> |
| |
| <p> |
| The return or result "parameters" of a Go function can be given names and |
| used as regular variables, just like the incoming parameters. |
| When named, they are initialized to the zero for their type when |
| the function begins; if the function executes a <code>return</code> statement |
| with no arguments, the current values of the result parameters are |
| used as the returned values. |
| </p> |
| |
| <p> |
| The names are not mandatory but they can make code shorter and clearer: |
| they're documentation. |
| If we name the results of <code>nextInt</code> it becomes |
| obvious which returned <code>int</code> |
| is which. |
| </p> |
| |
| <pre> |
| func nextInt(b []byte, pos int) (value, nextPos int) { |
| </pre> |
| |
| <p> |
| Because named results are initialized and tied to an unadorned return, they can simplify |
| as well as clarify. Here's a version |
| of <code>io.ReadFull</code> that uses them well: |
| </p> |
| |
| <pre> |
| func ReadFull(r Reader, buf []byte) (n int, err os.Error) { |
| for len(buf) > 0 && err != nil { |
| var nr int; |
| nr, err = r.Read(buf); |
| n += nr; |
| buf = buf[nr:len(buf)]; |
| } |
| return; |
| } |
| </pre> |
| |
| <h2>More to come</h2> |
| |
| <!--- |
| |
| <h2 id="idioms">Idioms</h2> |
| |
| <h3 id="struct-allocation">Allocate using literals</h3> |
| |
| <p> |
| 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. |
| </p> |
| |
| <pre> |
| length := Point{x, y}.Abs(); |
| </pre> |
| |
| <pre> |
| // Prepare RPCMessage to send to server |
| rpc := &RPCMessage { |
| Version: 1, |
| Header: &RPCHeader { |
| Id: nextId(), |
| Signature: sign(body), |
| Method: method, |
| }, |
| Body: body, |
| }; |
| </pre> |
| |
| <h3 id="buffer-slice">Use parallel assignment to slice a buffer</h3> |
| |
| <pre> |
| header, body, checksum := buf[0:20], buf[20:n-4], buf[n-4:n]; |
| </pre> |
| |
| <h2 id="errors">Errors</h2> |
| |
| <h3 id="error-returns">Return <code>os.Error</code>, not <code>bool</code></h3> |
| |
| <p> |
| Especially in libraries, functions tend to have multiple error modes. |
| Instead of returning a boolean to signal success, |
| return an <code>os.Error</code> that describes the failure. |
| Even if there is only one failure mode now, |
| there may be more later. |
| </p> |
| |
| <h3 id="error-context">Return structured errors</h3> |
| |
| Implementations of <code>os.Error</code> should |
| describe the error and provide context. |
| For example, <code>os.Open</code> returns an <code>os.PathError</code>: |
| |
| <a href="/src/pkg/os/file.go">/src/pkg/os/file.go</a>: |
| <pre> |
| // PathError records an error and the operation and |
| // file path that caused it. |
| type PathError struct { |
| Op string; |
| Path string; |
| Error Error; |
| } |
| |
| func (e *PathError) String() string { |
| return e.Op + " " + e.Path + ": " + e.Error.String(); |
| } |
| </pre> |
| |
| <p> |
| <code>PathError</code>'s <code>String</code> formats |
| the error nicely, including the operation and file name |
| tha failed; just printing the error generates a |
| message, such as |
| </p> |
| <pre> |
| open /etc/passwx: no such file or directory |
| </pre> |
| <p> |
| that is useful even if printed far from the call that |
| triggered it. |
| </p> |
| |
| <p> |
| Callers that care about the precise error details can |
| use a type switch or a type guard to look for specific |
| errors and extract details. For <code>PathErrors</code> |
| this might include examining the internal <code>Error</code> |
| to see if it is <code>os.EPERM</code> or <code>os.ENOENT</code>, |
| for instance. |
| </p> |
| |
| <h2 id="types">Programmer-defined types</h2> |
| |
| <h3 id="constructors">Use <code>NewTypeName</code> for constructors</h3> |
| |
| <p> |
| The constructor for the type <code>pkg.MyType</code> should |
| be named <code>pkg.NewMyType</code> and should return <code>*pkg.MyType</code>. |
| The implementation of <code>NewTypeName</code> often uses the |
| <a href="#struct-allocation">struct allocation idiom</a>. |
| </p> |
| |
| <a href="xxx">go/src/pkg/os/file.go</a>: |
| <pre> |
| func NewFile(fd int, name string) *File { |
| if file < 0 { |
| return nil |
| } |
| return &File{fd, name, nil, 0} |
| } |
| </pre> |
| |
| <p>Packages that export only a single type can |
| shorten <code>NewTypeName</code> to <code>New</code>; |
| the vector constructor is |
| <code>vector.New</code>, not <code>vector.NewVector</code>. |
| </p> |
| |
| <p> |
| A type that is intended to be allocated |
| as part of a larger struct may have an <code>Init</code> method |
| that must be called explicitly. |
| Conventionally, the <code>Init</code> method returns |
| the object being initialized, to make the constructor trivial: |
| </p> |
| |
| <a href="xxx">go/src/pkg/container/vector/vector.go</a>: |
| <pre> |
| func New(len int) *Vector { |
| return new(Vector).Init(len) |
| } |
| </pre> |
| |
| <h3 id="zero-value">Make the zero value meaningful</h3> |
| |
| <p> |
| In Go, newly allocated memory and newly declared variables are zeroed. |
| If a type is intended to be allocated without using a constructor |
| (for example, as part of a larger struct or declared as a local variable), |
| define the meaning of the zero value and arrange for that meaning |
| to be useful. |
| </p> |
| |
| <p> |
| For example, <code>sync.Mutex</code> does not |
| have an explicit constructor or <code>Init</code> method. |
| Instead, the zero value for a <code>sync.Mutex</code> |
| is defined to be an unlocked mutex. |
| </p> |
| |
| <h2 id="interfaces">Interfaces</h2> |
| |
| <h3 id="accept-interface-values">Accept interface values</h3> |
| |
| buffered i/o takes a Reader, not an os.File. XXX |
| |
| <h3 id="return-interface-values">Return interface values</h3> |
| |
| <p> |
| If a type exists only to implement an interface |
| and has no exported methods beyond that interface, |
| there is no need to publish the type itself. |
| Instead, write a constructor that returns an interface value. |
| </p> |
| |
| <p> |
| For example, both <code>crc32.NewIEEE()</code> and <code>adler32.New()</code> |
| return type <code>hash.Hash32</code>. |
| Substituting the CRC-32 algorithm for Adler-32 in a Go program |
| requires only changing the constructor call: |
| the rest of the code is unaffected by the change of algorithm. |
| </p> |
| |
| <h3 id="asdf">Use interface adapters to expand an implementation</h3> |
| |
| XXX |
| |
| <h3 id="fdsa">Use anonymous fields to incorporate an implementation</h3> |
| |
| XXX |
| |
| <h2>Data-Driven Programming</h2> |
| |
| <p> |
| tables |
| </p> |
| |
| <p> |
| XXX struct tags for marshalling. |
| template |
| eventually datafmt |
| </p> |
| |
| <h2>Concurrency</h2> |
| |
| <h3 id="share-memory">Share memory by communicating</h3> |
| |
| <p> |
| Do not communicate by sharing memory; |
| instead, share memory by communicating. |
| </p> |
| |
| <p> |
| XXX, more here. |
| </p> |
| |
| |
| <h2>Testing</h2> |
| |
| <h3 id="no-abort">Run tests to completion</h3> |
| |
| <p> |
| Tests should not stop early just because one case has misbehaved. |
| If at all possible, let tests continue, in order to characterize the |
| problem in more detail. |
| For example, it is more useful for a test to report that <code>isPrime</code> |
| gives the wrong answer for 4, 8, 16 and 32 than to report |
| that <code>isPrime</code> gives the wrong answer for 4 and therefore |
| no more tests were run. |
| XXX |
| test bottom up |
| test runs top to bottom |
| how to use gotest |
| XXX |
| </p> |
| |
| <h3 id="good-errors">Print useful errors when tests fail</h3> |
| |
| <p> |
| If a test fails, print a concise message explaining the context, |
| what happened, and what was expected. |
| Many testing environments encourage causing the |
| program to crash, but stack traces and core dumps |
| have low signal to noise ratios and require reconstructing |
| the situation from scratch. |
| The programmer who triggers the test failure may be someone |
| editing the code months later or even someone editing a different |
| package on which the code depends. |
| Time invested writing a good error message now pays off when |
| the test breaks later. |
| </p> |
| |
| <h3 id="data-driven-tests">Use data-driven tests</h3> |
| |
| <p> |
| Many tests reduce to running the same code multiple times, |
| with different input and expected output. |
| Instead of using cut and paste to write this code, |
| create a table of test cases and write a single test that |
| iterates over the table. |
| Once the table is written, you might find that it |
| serves well as input to multiple tests. For example, |
| a single table of encoded/decoded pairs can be |
| used by both <code>TestEncoder</code> and <code>TestDecoder</code>. |
| </p> |
| |
| <p> |
| This data-driven style dominates in the Go package tests. |
| <br> |
| <!-- search for for.*range here --> |
| </p> |
| |
| <h3 id="reflect.DeepEqual">Use reflect.DeepEqual to compare complex values</h3> |
| |
| <p> |
| The <code>reflect.DeepEqual</code> function tests |
| whether two complex data structures have equal values. |
| If a function returns a complex data structure, |
| <code>reflect.DeepEqual</code> combined with table-driven testing |
| makes it easy to check that the return value is |
| exactly as expected. |
| </p> |
| |
| <h2 id="be-consistent">Be consistent</h2> |
| |
| <p> |
| Programmers often want their style to be distinctive, |
| writing loops backwards or using custom spacing and |
| naming conventions. Such idiosyncracies come at a |
| price, however: by making the code look different, |
| they make it harder to understand. |
| Consistency trumps personal |
| expression in programming. |
| </p> |
| |
| <p> |
| If a program does the same thing twice, |
| it should do it the same way both times. |
| Conversely, if two different sections of a |
| program look different, the reader will |
| expect them to do different things. |
| </p> |
| |
| <p> |
| Consider <code>for</code> loops. |
| Traditionally, a loop over <code>n</code> |
| elements begins: |
| </p> |
| |
| <pre> |
| for i := 0; i < n; i++ { |
| </pre> |
| |
| <p> |
| Much of the time, the loop could run in the opposite order |
| and still be correct: |
| </p> |
| |
| <pre> |
| for i := n-1; i >= 0; i-- { |
| </pre> |
| |
| <p> |
| The convention |
| is to count up unless to do so would be incorrect. |
| A loop that counts down implicitly says “something |
| special is happening here.” |
| A reader who finds a program in which some |
| loops count up and the rest count down |
| will spend time trying to understand why. |
| </p> |
| |
| <p> |
| Loop direction is just one |
| programming decision that must be made |
| consistently; others include |
| formatting, naming variables and methods, |
| whether a type |
| has a constructor, what tests look like, and so on. |
| Why is this variable called <code>n</code> here and <code>cnt</code> there? |
| Why is the <code>Log</code> constructor <code>CreateLog</code> when |
| the <code>List</code> constructor is <code>NewList</code>? |
| Why is this data structure initialized using |
| a structure literal when that one |
| is initialized using individual assignments? |
| These questions distract from the important one: |
| what does the code do? |
| Moreover, internal consistency is important not only within a single file, |
| but also within the the surrounding source files. |
| When editing code, read the surrounding context |
| and try to mimic it as much as possible, even if it |
| disagrees with the rules here. |
| It should not be possible to tell which lines |
| you wrote or edited based on style alone. |
| Consistency about little things |
| lets readers concentrate on big ones. |
| </p> |
| |
| --> |
| |
| </div> |
| </body> |
| </html> |