]> Cypherpunks repositories - gostls13.git/commitdiff
Effective Go; draft
authorRuss Cox <rsc@golang.org>
Thu, 25 Jun 2009 16:38:35 +0000 (09:38 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 25 Jun 2009 16:38:35 +0000 (09:38 -0700)
TBR=r
OCL=30741
CL=30741

doc/effective_go.html [new file with mode: 0644]

diff --git a/doc/effective_go.html b/doc/effective_go.html
new file mode 100644 (file)
index 0000000..1e92552
--- /dev/null
@@ -0,0 +1,740 @@
+
+<h2 id="introduction">Introduction</h2>
+
+<p>
+Go is a new programming language.
+It eliminates some of the pitfalls in languages
+like C++ and Java but introduces other ones.
+Many remain the same.
+This page gives tips for writing clear, idiomatic Go code
+and points out common mistakes to avoid.
+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 be familiar with.
+</p>
+
+<h3 id="read">Read</h3>
+
+<p>
+The first step to improving as a writer is to read.
+This step is as necessary for programming as it is for prose,
+and it is skipped as often by programmers as by writers.
+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.  Read them.
+</p>
+
+<h3 id="be-consistent">Be consistent</h3>
+
+<p>
+Consistency makes programs easy to read.
+If a program says the same thing twice,
+it should say it the same way both times,
+so that the parallel structure is clear.
+Conversely, if two different sections of
+program look different, the reader will
+expect them to be doing different things.
+</p>
+
+<p>
+Consider <code>for</code> loops.
+Traditionally, a loop over <code>n</code>
+elements begins:
+</p>
+
+<pre>
+for i := 0; i &lt; 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 &gt;= 0; i-- {
+</pre>
+
+<p>
+The convention in most languages (including Go)
+is to count up unless doing so would be incorrect.
+A loop that counts down implicitly says &ldquo;there's
+a specific reason to count down here; this situation is special.&rdquo;
+A reader who finds a program in which half the
+loops count up and the other half count down
+will spend time trying to understand why.
+A programmer who inserts counting-down
+loops for variety wastes the reader's time.
+</p>
+
+<p>
+Loop direction is hardly the only
+programming decision which a programmer
+might want to use to be distinctive:
+tabs or spaces, choice of variable names,
+choice of method names, whether a type
+has a constructor, what tests look like, and on and on.
+As in the loop example, inconsistency
+sows confusion, and wastes time.
+Why is this variable called n here and cnt here?
+Why is the <code>Log</code> constructor <code>CreateLog</code> when
+the <code>Vector</code> constructor is <code>NewVector</code>?
+Why is this data structure initialized using
+a structure literal when this other one
+is initialized using individual assignments?
+Why is this idiom used here but not there?
+And on and on.
+These questions distract from the important one:
+what does the code do?
+Being consistent about little things
+lets readers concentrate on big ones.
+</p>
+
+<p>
+This document describes how to use Go effectively.
+Equally important, it describes how to use Go idiomatically,
+so that a Go programmer seeing your code for
+the first time can focus on what it does 
+and not why it is inconsistent with typical Go practices.
+Consistency trumps every item listed below.
+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.
+</p>
+
+<p>
+Internal consistency is important in a single file,
+but source files do not exist in isolation.
+Code must be consistent with the surrounding source file as well,
+or the same problems arise.
+</p>
+
+<h2 id="formatting">Formatting</h2>
+
+<p>
+Formatting issues are the most contentious
+but the least consequential.
+People adapt quite well to different formatting styles,
+even if at first the styles &ldquo;look weird.&rdquo;
+The most important consideration is that if everyone
+uses the same formatting, then a reader picking up an
+unfamiliar piece of code can focus on what
+the code does instead of what it looks like.
+Most of the local formatting style can and should be
+picked up by reading existing Go programs (see above).
+The following are the most common issues 
+that Google programmers run into.
+</p>
+
+<h3 id="tabs">Use tabs</h3>
+
+<p>
+The local style is to use tabs, not spaces, for indentation.
+</p>
+
+<h3 id="white-space">Trim trailing white space</h3>
+
+<p>
+Files should not contain trailing white space at the end of lines.
+The script <code>/home/rsc/bin/g4ws</code> removes trailing
+whitespace from all open files in the current g4 client.
+</p>
+
+<h3 id="line-wrapping">Don't wrap lines mechanically</h3>
+
+<p>
+Go has no 80-character limit.  Don't bother with fancy line
+wrapping just because a line is wider than a punched card.
+If you must wrap a line, indent with a single tab.
+</p>
+
+<h3 id="parens">Omit parentheses</h3>
+
+<p>Go does not require parentheses around the expression
+following the <code>for</code>, <code>if</code>, <code>range</code>,
+and <code>switch</code> keywords.
+</p>
+
+<h3 id="line-comments">Use line comments</h3>
+
+<p>
+Go provides C-style <code>/* */</code> block comments 
+and C++-style <code>//</code> line comments.
+The local style is to use line comments by default,
+reserving block comments for top-level package comments
+and commenting out large swaths of code.
+</p>
+
+<h3 id="doc-comments">Write doc comments</h3>
+
+<p>
+If a comment immediately precedes a top-level declaration,
+the <a href="/">Go documentation server</a>
+uses that comment as the documentation
+for the constant, function, package, type or variable being declared.
+To detach a comment from a declaration, insert a blank
+line between them.
+</p>
+
+<p>
+Every exported (capitalized) name in a program should
+have a doc comment, as should the package declaration itself.
+</p>
+
+<p>
+Doc comments consist of complete English sentences.
+The first sentence should be a one-sentence summary that
+starts with the name being declared:
+</p>
+
+<pre>
+// Quote returns a double-quoted Go string literal
+// representing s.  The returned string s uses Go escape
+// sequences (\t, \n, \xFF, \u0100) for control characters
+// and non-ASCII characters.
+func Quote(s string) string {
+</pre>
+
+<p>
+instead of:
+</p>
+
+<pre class="bad">
+/* not Go style */
+// Return a double-quoted Go string literal representing s....
+func Quote(s string) string {
+</pre>
+
+<p>
+The complete English sentence form admits
+a wider variety of automated presentations.
+</p>
+
+
+<h3 id="ascii-art">Avoid ASCII Art</h3>
+
+<p>
+Go programs are meant to read equally well using 
+fixed-width and variable-width fonts.
+Don't use fancy formattings that depend on fixed-width fonts.
+In particular, don't assume that a single space is the same
+width as every other character.
+If you need to make a columnated table, use tabs to separate
+the columns and the pretty printer (in progress) will make
+sure the columns are lined up properly in the output.
+</p>
+
+<p>
+If you must use comments to separate
+sections in a file, use a simple block comment:
+</p>
+
+<pre>
+/*
+ * Helper routines for simplifying the fetching of optional fields of basic type.
+ * If the field is missing, they return the zero for the type.
+ */
+</pre>
+
+<p>
+instead of:
+</p>
+
+<pre class="bad">
+/* not Go style */
+//////////////////////////////////////////////////////////////////////
+// Helper routines for simplifying the fetching of optional fields of basic type.
+// If the field is missing, they return the zero for the type.
+</pre>
+
+<p>
+Comments are text, not HTML, and not any kind of markup.
+Refrain from ASCII embellishment like *this* or /this/.
+As usual, read the Go sources for examples.
+</p>
+
+<h2 id="names">Names</h2>
+
+<h3 id="mixed-caps">Use MixedCaps</h3>
+
+<p>
+Go uses the case of the first letter in a name to decide
+whether the name is visible in other packages.
+In Go, multiword names use MixedCaps or mixedCaps
+rather than underscores.
+</p>
+
+<h3 id="package-names">Use short package names</h3>
+
+<p>
+Package names are lowercase single-word names:
+there should be no need for underscore or mixedCaps.
+The package name is conventionally the base name of
+the source directory: the package in <code>src/pkg/container/vector</code>
+is installed as <code>"container/vector"</code> but has name vector,
+not <code>container_vector</code> and not <code>containerVector</code>.
+The package name is only the default name used
+when importing the package; it need not be a unique
+identifier.
+</p>
+
+<h3 id="name-length">Avoid lengthy names</h3>
+
+<p>
+A name's length should not exceed its information content.
+For a function-local variable
+in scope only for a few lines, the name <code>i</code> conveys just
+as much information as <code>index</code> or <code>idx</code> and is easier to read.
+On the same note, <code>i</code> and <code>j</code> are better pair of names for
+index variables than <code>i1</code> and <code>i2</code> (or, worse, <code>index1</code> and <code>index2</code>),
+because they are easier to tell apart when reading
+the program quickly.
+</p>
+
+<p>
+Exported names must convey more information,
+because they appear in a larger variety of contexts.
+Even so, longer names are not always better,
+and the package name can help convey information:
+the buffered <code>Reader</code> is <code>bufio.Reader</code>, not <code>bufio.BufReader</code>.
+Similarly, <code>once.Do</code> is as precise and evocative as
+<code>once.DoOrWaitUntilDone</code>, and <code>once.Do(f)</code> reads
+better than <code>once.DoOrWaitUntilDone(f)</code>.
+Contrary to popular belief, encoding small essays into
+function names does not make it possible
+to use them without documentation.
+</p>
+
+<h3 id="interfacers">Use the -er convention for interface names</h3>
+
+<p>
+One-method interfaces are conventionally named by
+the method name plus the -er suffix: <code>Reader</code>,
+<code>Writer</code>, <code>Formatter</code>.  Using an interface name distinct
+from the method name keeps an anonymous struct
+field of type <code>Reader</code> from conflicting with its own 
+<code>Read</code> method.
+</p>
+
+<h3 id="common-names">Use canonical names</h3>
+
+<p>
+A few method names—<code>Read</code>, <code>Write</code>, <code>Close</code>, <code>Flush</code>, <code>String</code>—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, equally important, the same signature.
+</p>
+
+<p>
+Some function-local variables have canonical names too.
+Just as <code>i</code> is idiomatic in Go for an
+index variable, <code>n</code> is idiomatic for a count, <code>b</code> for a <code>[]byte</code>,
+<code>s</code> for a <code>string</code>, <code>r</code> for a <code>Reader</code>,
+<code>err</code> for an <code>os.Error</code>
+and so on.
+Don't mix shorthands: it is especially confusing to
+have two different variables <code>i</code> and <code>idx</code>,
+or <code>n</code> and <code>cnt</code>.
+</p>
+
+<h2 id="idioms">Idioms</h2>
+
+TODO: Add links to code once godoc can handle it.
+
+<h3 id="address-literals">Address literals to allocate and initialize</h3>
+
+<p>
+Taking the address of a struct or array literal evaluates to a
+new instance each time it is evaluated.
+Use these expressions to avoid the repetition of filling
+out a data structure.
+</p>
+
+
+<h3 id="buffer-slice">Use parallel assignment to slice a buffer</h3>
+
+<pre>
+hdr, body, checksum := buf[0:20], buf[20:len(buf)], buf[len(buf)-4:len(buf)];
+</pre>
+
+<h2 id="control-flow">Control Flow</h2>
+
+<h3 id="else">Omit needless else bodies</h3>
+
+<p>
+If an <code>if</code> body doesn't flow off the end of the
+body—that is, the body ends in <code>break</code>, <code>continue</code>,
+<code>goto</code>, or <code>return</code>—it is preferable to omit the <code>else</code>.
+</p>
+
+<p>
+For example:
+</p>
+
+<pre>
+f, err := os.Open(name, os.O_RDONLY, 0);
+if err != nil {
+       return err;
+}
+codeUsing(f);
+f.Close();
+moreCode();
+</pre>
+
+<p>
+is preferable to:
+
+<pre class="bad">
+/* not Go style */
+if f, err := os.Open(name, os.O_RDONLY, 0); err != nil {
+       return err;
+} else {
+       codeUsing(f);
+       f.Close();
+}
+moreCode();
+</pre>
+
+<p>
+The first form
+avoids unnecessary indentation
+and makes it clear that <code>moreCode()</code>
+only runs when <code>f.Close()</code> does.
+</p>
+
+<h3 id="switch">Switch</h3>
+
+<p>
+Go's <code>switch</code> is more powerful than C's.
+When an <code>if</code>-<code>else if</code>-<code>else</code> chain has three or more bodies,
+or an <code>if</code> condition has a long list of alternatives,
+consider rewriting it using <code>switch</code>.
+</p>
+
+<a href="/src/pkg/bytes/bytes.go">go/src/pkg/bytes/bytes.go</a>:
+<pre>
+// Compare returns an integer comparing the two byte arrays lexicographically.
+// The result will be 0 if a==b, -1 if a &lt; b, and +1 if a &gt; b
+func Compare(a, b []byte) int {
+    for i := 0; i &lt; len(a) &amp;&amp; i &lt; len(b); i++ {
+        switch {
+        case a[i] &gt; b[i]:
+            return 1
+        case a[i] &lt; b[i]:
+            return -1
+        }
+    }
+    switch {
+    case len(a) &lt; len(b):
+        return -1
+    case len(a) &gt; len(b):
+        return 1
+    }
+    return 0
+}
+</pre>
+
+<a href="/src/pkg/http/url.go">go/src/pkg/http/url.go</a>:
+<pre>
+func unhex(c byte) byte {
+    switch {
+    case '0' &lt;= c &amp;&amp; c &lt;= '9':
+        return c - '0'
+    case 'a' &lt;= c &amp;&amp; c &lt;= 'f':
+        return c - 'a' + 10
+    case 'A' &lt;= c &amp;&amp; c &lt;= 'F':
+        return c - 'A' + 10
+    }
+    return 0
+}
+</pre>
+
+<a href="/src/pkg/http/url.go">go/src/pkg/http/url.go</a>:
+<pre>
+func shouldEscape(c byte) bool {
+    switch c {
+    case ' ', '?', '&', '=', '#', '+', '%':
+        return true
+    }
+    return false
+}
+</pre>
+
+<h2 id="functions">Functions</h2>
+
+<h3 id="omit-wrappers">Omit needless wrappers</h3>
+
+<p>
+Functions are great for factoring out common functionality.
+If a function is only called once,
+ask whether the function is really necessary,
+especially if it is just a short wrapper around another function.
+This style runs rampant in C++ code: wrappers
+call wrappers that call wrappers that call wrappers.
+Doing this hinders people trying to understand the program,
+not to mention computers trying to execute it.
+</p>
+
+<h3 id="multiple-returns">Return multiple values</h3>
+
+<p>
+If a function must return multiple values, it can
+do so directly.
+The C &ldquo;pass in a pointer to a return value&rdquo;
+idiom is dead.
+</p>
+
+
+<h2 id="errors">Errors</h2>
+
+<h3 id="handle-errors-first">Handle errors first</h3>
+
+<p>
+Errors 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 jumps,
+so that there is <a href="#else">no need for an explicit else</a>.
+</p>
+
+<pre>
+f, err := os.Open(name, os.O_RDONLY, 0);
+if err != nil {
+       return err;
+}
+codeUsing(f);
+f.Close();
+moreCode();
+</pre>
+
+is preferable to:
+
+<pre class="bad">
+/* not Go style */
+f, err := os.Open(name, os.O_RDONLY, 0);
+if err == nil {
+       codeUsing(f);
+       f.Close();
+} else {
+       return err;
+}
+moreCode();
+</pre>
+
+<h3 id="error-returns">Return <code>os.Error</code>, not <code>bool</code></h3>
+
+<p>
+Few functions have just one failure mode.
+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>s should
+describe the error but also include 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>
+XXX definition of PathError and .String
+</pre>
+
+<code>PathError</code>'s <code>String</code> formats
+the error nicely and is the usual way the error gets used.
+Callers that care about the precise error details can
+use a type switch or a type guard to look for specific
+errors and then extract details.
+
+<pre>
+XXX example here - MkdirAll
+</pre>
+
+<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="#allocating-a-struct">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 &lt; 0 {
+               return nil
+       }
+       return &amp;File{fd, name, nil, 0}
+}
+</pre>
+
+<p>Packages that export only a single type sometimes
+shorten <code>NewTypeName</code> to <code>New</code>;
+for example, 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 cannot distinguish the two algorithms.
+</p>
+
+<h3 id="">Use interface adapters to expand an implementation</h3>
+
+XXX
+
+<h3 id="">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 2, 3, 5, and 7 (or for 2, 4, 8, and 16) than to report
+that <code>isPrime</code> gives the wrong answer for 2 and therefore
+no more tests were run.
+</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>
+
+</div>
+</body>
+</html>