2009-10-01 15:08:00 -06:00
|
|
|
<!-- Effective Go -->
|
2009-09-29 12:57:28 -06:00
|
|
|
|
|
|
|
<!-- interfaces; slices; embedding; value vs. pointer receivers; methods on anything; errors; testing -->
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<h2 id="introduction">Introduction</h2>
|
|
|
|
|
2009-08-03 15:07:19 -06:00
|
|
|
<p>
|
2009-10-05 15:48:57 -06:00
|
|
|
Go is a new language. Although it borrows ideas from
|
|
|
|
existing languages,
|
|
|
|
it has unusual properties that make effective Go programs
|
|
|
|
different in character from programs in its relatives.
|
2009-08-19 14:24:24 -06:00
|
|
|
A straightforward translation of a C++ or Java program into Go
|
2009-10-05 15:48:57 -06:00
|
|
|
is unlikely to produce a satisfactory result—Java programs
|
2009-08-19 14:24:24 -06:00
|
|
|
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
|
2009-08-03 15:07:19 -06:00
|
|
|
and idioms.
|
2009-08-19 14:24:24 -06:00
|
|
|
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.
|
2009-08-03 15:07:19 -06:00
|
|
|
</p>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<p>
|
2009-08-19 14:24:24 -06:00
|
|
|
This document gives tips for writing clear, idiomatic Go code.
|
2009-06-25 10:38:35 -06:00
|
|
|
It augments the <a href="go_spec.html">language specification</a>
|
|
|
|
and the <a href="go_tutorial.html">tutorial</a>, both of which you
|
2009-07-06 16:15:56 -06:00
|
|
|
should read first.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
<h3 id="read">Examples</h3>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<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
|
2009-08-19 14:24:24 -06:00
|
|
|
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.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<h2 id="formatting">Formatting</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Formatting issues are the most contentious
|
|
|
|
but the least consequential.
|
2009-08-19 14:24:24 -06:00
|
|
|
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.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
<p>
|
2009-08-19 17:39:25 -06:00
|
|
|
With Go we take an unusual
|
2009-08-19 14:24:24 -06:00
|
|
|
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>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-19 14:24:24 -06:00
|
|
|
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
|
2009-07-31 12:41:30 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
<pre>
|
|
|
|
type T struct {
|
|
|
|
name string; // name of the object
|
|
|
|
value int; // its value
|
|
|
|
}
|
|
|
|
</pre>
|
2009-07-31 12:41:30 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-19 14:24:24 -06:00
|
|
|
<code>gofmt</code> will make the columns line up:
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
<pre>
|
|
|
|
type T struct {
|
|
|
|
name string; // name of the object
|
|
|
|
value int; // its value
|
|
|
|
}
|
|
|
|
</pre>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-19 14:24:24 -06:00
|
|
|
All code in the libraries has been formatted with <code>gofmt</code>.
|
|
|
|
<font color=red>TODO</font>
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p>
|
2009-08-19 14:24:24 -06:00
|
|
|
Some formatting details remain. Very briefly:
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
<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>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
<h2>Commentary</h2>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-10-01 15:08:00 -06:00
|
|
|
Go provides C-style <code>/* */</code> block comments
|
2009-06-25 10:38:35 -06:00
|
|
|
and C++-style <code>//</code> line comments.
|
2009-08-19 17:39:25 -06:00
|
|
|
Line comments are the norm;
|
|
|
|
block comments appear mostly as package comments and
|
|
|
|
are also useful to disable large swaths of code.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-19 17:39:25 -06:00
|
|
|
<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>
|
2009-07-31 18:54:00 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-19 17:39:25 -06:00
|
|
|
Every package should have a <i>package comment</i>, a block
|
2009-07-31 18:54:00 -06:00
|
|
|
comment preceding the package clause.
|
2009-08-19 17:39:25 -06:00
|
|
|
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
|
2009-07-31 18:54:00 -06:00
|
|
|
provide information relevant to the package as a whole.
|
2009-08-19 17:39:25 -06:00
|
|
|
It will appear first on the <code>godoc</code> page and
|
|
|
|
should set up the detailed documentation that follows.
|
2009-07-31 18:54:00 -06:00
|
|
|
</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>
|
2009-08-19 17:39:25 -06:00
|
|
|
If the package is simple, the package comment can be brief.
|
2009-07-31 18:54:00 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
// The path package implements utility routines for
|
|
|
|
// manipulating slash-separated filename paths.
|
|
|
|
</pre>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<p>
|
2009-08-19 17:39:25 -06:00
|
|
|
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.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
2009-08-19 17:39:25 -06:00
|
|
|
Inside a package, any comment immediately preceding a top-level declaration
|
|
|
|
serves as a <i>doc comment</i> for that declaration.
|
2009-06-25 10:38:35 -06:00
|
|
|
Every exported (capitalized) name in a program should
|
2009-08-19 17:39:25 -06:00
|
|
|
have a doc comment.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
2009-08-19 17:39:25 -06:00
|
|
|
Doc comments work best as complete English sentences, which allow
|
|
|
|
a wide variety of automated presentations.
|
2009-06-25 10:38:35 -06:00
|
|
|
The first sentence should be a one-sentence summary that
|
|
|
|
starts with the name being declared:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
2009-08-19 17:39:25 -06:00
|
|
|
// 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) {
|
2009-06-25 10:38:35 -06:00
|
|
|
</pre>
|
|
|
|
|
2009-07-31 18:54:00 -06:00
|
|
|
<p>
|
|
|
|
Go's declaration syntax allows grouping of declarations.
|
2009-08-19 17:39:25 -06:00
|
|
|
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.
|
2009-07-31 18:54:00 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
2009-08-19 17:39:25 -06:00
|
|
|
// Error codes returned by failures to parse an expression.
|
|
|
|
var (
|
|
|
|
ErrInternal = os.NewError("internal error");
|
|
|
|
ErrUnmatchedLpar = os.NewError("unmatched '('");
|
|
|
|
ErrUnmatchedRpar = os.NewError("unmatched ')'");
|
2009-07-31 18:54:00 -06:00
|
|
|
...
|
|
|
|
)
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
2009-08-19 17:39:25 -06:00
|
|
|
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.
|
2009-07-31 18:54:00 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
var (
|
2009-08-03 15:07:19 -06:00
|
|
|
countLock sync.Mutex;
|
2009-07-31 18:54:00 -06:00
|
|
|
inputCount uint32;
|
|
|
|
outputCount uint32;
|
|
|
|
errorCount uint32;
|
|
|
|
)
|
|
|
|
</pre>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<h2 id="names">Names</h2>
|
|
|
|
|
2009-08-20 16:39:41 -06:00
|
|
|
<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
|
2009-10-05 15:48:57 -06:00
|
|
|
first character is an upper case letter.
|
2009-08-20 16:39:41 -06:00
|
|
|
It's therefore worth spending a little time talking about naming conventions
|
|
|
|
in Go programs.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<h3 id="package-names">Package names</h3>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-20 16:39:41 -06:00
|
|
|
When a package is imported, the package name becomes an accessor for the
|
|
|
|
contents. After
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-20 16:39:41 -06:00
|
|
|
<pre>
|
|
|
|
import "bytes"
|
|
|
|
</pre>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-20 16:39:41 -06:00
|
|
|
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.
|
2009-10-05 15:48:57 -06:00
|
|
|
In any case, confusion is rare because the file name in the import
|
|
|
|
defines which version is being used.
|
2009-08-20 16:39:41 -06:00
|
|
|
</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>
|
2009-07-06 16:15:56 -06:00
|
|
|
is installed as <code>"container/vector"</code> but has name <code>vector</code>,
|
2009-06-25 10:38:35 -06:00
|
|
|
not <code>container_vector</code> and not <code>containerVector</code>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
2009-08-20 16:39:41 -06:00
|
|
|
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>.
|
2009-09-27 18:59:36 -06:00
|
|
|
Similarly, the constructor for <code>vector.Vector</code>
|
2009-10-05 15:48:57 -06:00
|
|
|
would normally be called <code>NewVector</code> but since
|
2009-09-27 18:59:36 -06:00
|
|
|
<code>Vector</code> is the only type exported by the package, and since the
|
|
|
|
package is called <code>vector</code>, it's called just <code>New</code>,
|
|
|
|
which clients of the package see as <code>vector.New</code>.
|
2009-08-20 16:39:41 -06:00
|
|
|
Use the package structure to help you choose good names.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
2009-08-20 16:39:41 -06:00
|
|
|
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.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-20 16:39:41 -06:00
|
|
|
<h3 id="interface-names">Interface names</h3>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-20 16:39:41 -06:00
|
|
|
By convention, one-method interfaces are named by
|
2009-06-25 10:38:35 -06:00
|
|
|
the method name plus the -er suffix: <code>Reader</code>,
|
2009-08-20 16:39:41 -06:00
|
|
|
<code>Writer</code>, <code>Formatter</code> etc.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
2009-08-20 16:39:41 -06:00
|
|
|
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
|
2009-06-25 10:38:35 -06:00
|
|
|
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,
|
2009-08-20 16:39:41 -06:00
|
|
|
give it the same name and signature;
|
|
|
|
call your string-converter method <code>String</code> not <code>ToString</code>.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-20 16:39:41 -06:00
|
|
|
<h3 id="mixed-caps">MixedCaps</h3>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<p>
|
2009-10-05 15:48:57 -06:00
|
|
|
Finally, the convention in Go is to use <code>MixedCaps</code>
|
2009-08-20 16:39:41 -06:00
|
|
|
or <code>mixedCaps</code> rather than underscores to write
|
|
|
|
multiword names.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<h2 id="semicolons">Semicolons</h2>
|
2009-08-20 16:39:41 -06:00
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<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>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<pre>
|
2009-09-02 17:41:41 -06:00
|
|
|
func CopyInBackground(dst, src chan Item) {
|
2009-08-23 15:00:28 -06:00
|
|
|
go func() { for { dst <- <-src } }()
|
|
|
|
}
|
|
|
|
</pre>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-09-27 18:59:36 -06:00
|
|
|
In fact, semicolons can be omitted at the end of any "StatementList" in the
|
2009-08-23 15:00:28 -06:00
|
|
|
grammar, which includes things like cases in <code>switch</code>
|
|
|
|
statements:
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-07-31 18:54:00 -06:00
|
|
|
<pre>
|
2009-08-23 15:00:28 -06:00
|
|
|
switch {
|
|
|
|
case a < b:
|
|
|
|
return -1
|
|
|
|
case a == b:
|
|
|
|
return 0
|
|
|
|
case a > b:
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
</pre>
|
2009-08-13 12:29:05 -06:00
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<p>
|
2009-09-02 17:41:41 -06:00
|
|
|
The grammar accepts an empty statement after any statement list, which
|
2009-08-23 15:00:28 -06:00
|
|
|
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>.
|
2009-10-05 15:48:57 -06:00
|
|
|
The syntax is also slightly different:
|
|
|
|
parentheses are not required
|
2009-08-23 15:00:28 -06:00
|
|
|
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>
|
2009-08-19 14:24:24 -06:00
|
|
|
<pre>
|
2009-08-23 15:00:28 -06:00
|
|
|
if x > 0 {
|
|
|
|
return y
|
|
|
|
}
|
2009-07-31 18:54:00 -06:00
|
|
|
</pre>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<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>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<pre>
|
2009-08-23 15:00:28 -06:00
|
|
|
if err := file.Chmod(0664); err != nil {
|
|
|
|
log.Stderr(err)
|
|
|
|
}
|
2009-06-25 10:38:35 -06:00
|
|
|
</pre>
|
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<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>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<pre>
|
|
|
|
f, err := os.Open(name, os.O_RDONLY, 0);
|
|
|
|
if err != nil {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
codeUsing(f);
|
|
|
|
</pre>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-08-23 15:00:28 -06:00
|
|
|
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:
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
f, err := os.Open(name, os.O_RDONLY, 0);
|
|
|
|
if err != nil {
|
2009-08-23 15:00:28 -06:00
|
|
|
return err;
|
2009-06-25 10:38:35 -06:00
|
|
|
}
|
2009-08-23 15:00:28 -06:00
|
|
|
d, err := f.Stat();
|
|
|
|
if err != nil {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
codeUsing(f, d);
|
2009-06-25 10:38:35 -06:00
|
|
|
</pre>
|
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
|
2009-09-02 17:41:41 -06:00
|
|
|
<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>
|
2009-09-08 18:11:57 -06:00
|
|
|
// Like a C for
|
2009-09-02 17:41:41 -06:00
|
|
|
for init; condition; post { }
|
|
|
|
|
2009-09-08 18:11:57 -06:00
|
|
|
// Like a C while
|
2009-09-02 17:41:41 -06:00
|
|
|
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;
|
2009-10-05 15:48:57 -06:00
|
|
|
for _, value := range m { // key is unused
|
2009-09-02 17:41:41 -06:00
|
|
|
sum += value
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
2009-09-08 18:11:57 -06:00
|
|
|
<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>
|
|
|
|
|
2009-09-02 17:41:41 -06:00
|
|
|
<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>
|
2009-09-08 18:11:57 -06:00
|
|
|
you should use parallel assignment:
|
2009-09-02 17:41:41 -06:00
|
|
|
</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>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<h3 id="switch">Switch</h3>
|
|
|
|
|
|
|
|
<p>
|
2009-07-06 16:15:56 -06:00
|
|
|
Go's <code>switch</code> is more general than C's.
|
2009-08-23 15:00:28 -06:00
|
|
|
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>:
|
2009-06-25 10:38:35 -06:00
|
|
|
</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>
|
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<p>
|
|
|
|
There is no automatic fall through, but cases can be presented
|
|
|
|
in comma-separated lists:
|
2009-06-25 10:38:35 -06:00
|
|
|
<pre>
|
|
|
|
func shouldEscape(c byte) bool {
|
|
|
|
switch c {
|
2009-07-06 16:15:56 -06:00
|
|
|
case ' ', '?', '&', '=', '#', '+', '%':
|
2009-06-25 10:38:35 -06:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<p>
|
|
|
|
Here's a comparison routine for byte arrays that uses two
|
|
|
|
<code>switch</code> statements:
|
2009-07-06 16:15:56 -06:00
|
|
|
<pre>
|
2009-07-31 18:54:00 -06:00
|
|
|
// Compare returns an integer comparing the two byte arrays
|
|
|
|
// lexicographically.
|
2009-08-23 15:00:28 -06:00
|
|
|
// The result will be 0 if a == b, -1 if a < b, and +1 if a > b
|
2009-07-06 16:15:56 -06:00
|
|
|
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>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<h2 id="functions">Functions</h2>
|
|
|
|
|
2009-09-14 11:40:44 -06:00
|
|
|
<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
|
2009-10-05 15:48:57 -06:00
|
|
|
improve on a couple of clumsy idioms in C programs: in-band
|
2009-09-14 11:40:44 -06:00
|
|
|
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
|
2009-10-05 15:48:57 -06:00
|
|
|
value to simulate a reference parameter.
|
|
|
|
Here's a simple-minded function to
|
2009-09-14 11:40:44 -06:00
|
|
|
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>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-09-14 11:40:44 -06:00
|
|
|
The return or result "parameters" of a Go function can be given names and
|
|
|
|
used as regular variables, just like the incoming parameters.
|
2009-10-05 15:48:57 -06:00
|
|
|
When named, they are initialized to the zero values for their types when
|
2009-09-14 11:40:44 -06:00
|
|
|
the function begins; if the function executes a <code>return</code> statement
|
2009-10-01 15:08:00 -06:00
|
|
|
with no arguments, the current values of the result parameters are
|
2009-09-14 11:40:44 -06:00
|
|
|
used as the returned values.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-09-14 11:40:44 -06:00
|
|
|
<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>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<p>
|
2009-09-14 11:40:44 -06:00
|
|
|
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:
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-09-14 11:40:44 -06:00
|
|
|
<pre>
|
|
|
|
func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
|
2009-09-27 18:59:36 -06:00
|
|
|
for len(buf) > 0 && err != nil {
|
2009-09-14 11:40:44 -06:00
|
|
|
var nr int;
|
|
|
|
nr, err = r.Read(buf);
|
|
|
|
n += nr;
|
|
|
|
buf = buf[nr:len(buf)];
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
2009-09-27 18:59:36 -06:00
|
|
|
<h2 id="data">Data</h2>
|
2009-09-14 11:40:44 -06:00
|
|
|
|
2009-09-27 18:59:36 -06:00
|
|
|
<h3 id="allocation_new">Allocation with <code>new()</code></h3>
|
2009-09-14 11:40:44 -06:00
|
|
|
|
2009-09-27 18:59:36 -06:00
|
|
|
<p>
|
|
|
|
Go has two allocation primitives, <code>new()</code> and <code>make()</code>.
|
|
|
|
They do different things and apply to different types, which can be confusing,
|
|
|
|
but the rules are simple.
|
|
|
|
Let's talk about <code>new()</code> first.
|
|
|
|
It's a built-in function essentially the same as its namesakes
|
|
|
|
in other languages: it allocates zeroed storage for a new item of type
|
|
|
|
<code>T</code> and returns its address, a value of type <code>*T</code>.
|
|
|
|
In Go terminology, it returns a pointer to a newly allocated zero value of type
|
|
|
|
<code>T</code>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Since the memory returned by <code>new()</code> is zeroed, it's helpful to arrange that the
|
|
|
|
zeroed object can be used without further initialization. This means a user of
|
|
|
|
the data structure can create one with <code>new()</code> and get right to
|
|
|
|
work.
|
|
|
|
For example, the documentation for <code>bytes.Buffer</code> states that
|
|
|
|
"the zero value for <code>Buffer</code> is an empty buffer ready to use."
|
|
|
|
Similarly, <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>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The zero-value-is-useful property works transitively. Consider this type declaration:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
type SyncedBuffer struct {
|
|
|
|
lock sync.Mutex;
|
|
|
|
buffer bytes.Buffer;
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Values of type <code>SyncedBuffer</code> are also ready to use immediately upon allocation
|
|
|
|
or just declaration. In this snippet, both <code>p</code> and <code>v</code> will work
|
|
|
|
correctly without further arrangement:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
p := new(SyncedBuffer); // type *SyncedBuffer
|
|
|
|
var v SyncedBuffer; // type SyncedBuffer
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<h3 id="composite_literals">Constructors and composite literals</h3>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Sometimes the zero value isn't good enough and an initializing
|
|
|
|
constructor is necessary, as in this example derived from
|
|
|
|
package <code>os</code>:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
func NewFile(fd int, name string) *File {
|
|
|
|
if fd < 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
f := new(File);
|
|
|
|
f.fd = fd;
|
|
|
|
f.name = name;
|
|
|
|
f.error = nil;
|
|
|
|
f.dirinfo = nil;
|
|
|
|
f.nepipe = 0;
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
There's a lot of boilerplate in there. We can simplify it
|
|
|
|
using a <i>composite literal</i>, which is
|
|
|
|
an expression that creates a
|
|
|
|
new instance each time it is evaluated.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
func NewFile(fd int, name string) *File {
|
|
|
|
if file < 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
f := File{fd, name, nil, 0};
|
|
|
|
return &f;
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Note that it's perfectly OK to return the address of a local variable;
|
|
|
|
the storage associated with the variable survives after the function
|
|
|
|
returns.
|
2009-10-05 15:48:57 -06:00
|
|
|
In fact, taking the address of a composite literal
|
|
|
|
allocates a fresh instance each time it is evaluated,
|
|
|
|
so we can combine these last two lines:
|
2009-09-27 18:59:36 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
return &File{fd, name, nil, 0};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The fields of a composite literal are laid out in order and must all be present.
|
|
|
|
However, by labeling the elements explicitly as <i>field</i><code>:</code><i>value</i>
|
|
|
|
pairs, the initializers can appear in any
|
|
|
|
order, with the missing ones left as their respective zero values. Thus we could say
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
return &File{fd: fd, name: name}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
As a limiting case, if a composite literal contains no fields at all, it creates
|
|
|
|
a zero value for the type. These two expressions are equivalent:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
new(File)
|
|
|
|
&File{}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Composite literals can also be created for arrays, slices, and maps,
|
|
|
|
with the field labels being indices or map keys as appropriate.
|
|
|
|
In these examples, the initializations work regardless of the values of <code>EnoError</code>,
|
|
|
|
<code>Eio</code>, and <code>Einval</code>, as long as they are distinct:
|
|
|
|
</p>
|
2009-08-23 15:00:28 -06:00
|
|
|
|
2009-09-27 18:59:36 -06:00
|
|
|
<pre>
|
|
|
|
a := [...]string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"};
|
|
|
|
s := []string {Enone: "no error", Eio: "Eio", Einval: "invalid argument"};
|
|
|
|
m := map[int]string{Enone: "no error", Eio: "Eio", Einval: "invalid argument"};
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<h3 id="allocation_make">Allocation with <code>make()</code></h3>
|
2009-08-23 15:00:28 -06:00
|
|
|
|
|
|
|
<p>
|
2009-09-27 18:59:36 -06:00
|
|
|
Back to allocation.
|
|
|
|
The built-in function <code>make(T, </code><i>args</i><code>)</code> serves
|
|
|
|
a purpose different from <code>new(T)</code>.
|
|
|
|
It creates slices, maps, and channels only, and it returns an initialized (not zero)
|
|
|
|
value of type <code>T</code>, not <code>*T</code>.
|
|
|
|
The reason for the distinction
|
|
|
|
is that these three types are, under the covers, references to data structures that
|
|
|
|
must be initialized before use.
|
|
|
|
A slice, for example, is a three-item descriptor
|
|
|
|
containing a pointer to the data (inside an array), the length, and the
|
|
|
|
capacity; until those items are initialized, the slice is <code>nil</code>.
|
2009-10-01 15:08:00 -06:00
|
|
|
For slices, maps, and channels,
|
2009-09-27 18:59:36 -06:00
|
|
|
<code>make</code> initializes the internal data structure and prepares
|
|
|
|
the value for use.
|
|
|
|
For instance,
|
2009-08-23 15:00:28 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
2009-09-27 18:59:36 -06:00
|
|
|
make([]int, 10, 100)
|
2009-08-23 15:00:28 -06:00
|
|
|
</pre>
|
|
|
|
|
2009-09-27 18:59:36 -06:00
|
|
|
<p>
|
|
|
|
allocates an array of 100 ints and then creates a slice
|
|
|
|
structure with length 10 and a capacity of 100 pointing at the first
|
|
|
|
10 elements of the array.
|
|
|
|
(When making a slice, the capacity can be omitted; see the section on slices
|
|
|
|
for more information.)
|
|
|
|
In contrast, <code>new([]int)</code> returns a pointer to a newly allocated, zeroed slice
|
|
|
|
structure, that is, a pointer to a <code>nil</code> slice value.
|
|
|
|
|
|
|
|
<p>
|
|
|
|
These examples illustrate the difference between <code>new()</code> and
|
|
|
|
<code>make()</code>:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
var p *[]int = new([]int); // allocates slice structure; *p == nil; rarely useful
|
|
|
|
var v []int = make([]int, 100); // v now refers to a new array of 100 ints
|
|
|
|
|
|
|
|
// Unnecessarily complex:
|
|
|
|
var p *[]int = new([]int);
|
|
|
|
*p = make([]int, 100, 100);
|
|
|
|
|
|
|
|
// Idiomatic:
|
|
|
|
v := make([]int, 100);
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Remember that <code>make()</code> applies only to maps, slices and channels.
|
|
|
|
To obtain an explicit pointer allocate with <code>new()</code>.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h3 id="arrays">Arrays</h3>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Arrays are useful when planning the detailed layout of memory and sometimes
|
|
|
|
can help avoid allocation but primarily
|
|
|
|
they are a building block for slices, the subject of the next section.
|
|
|
|
To lay the foundation for that topic, here are a few words about arrays.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
There are major differences between the ways arrays work in Go and C.
|
|
|
|
In Go:
|
|
|
|
</p>
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
|
|
Arrays are values. Assigning one array to another copies all the elements.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
In particular, if you pass an array to a function, it
|
|
|
|
will receive a <i>copy</i> of the array, not a pointer to it.
|
|
|
|
<li>
|
|
|
|
The size of an array is part of its type. The types <code>[10]int</code>
|
|
|
|
and <code>[20]int</code> are distinct.
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
The value property can be useful but also expensive; if you want C-like behavior and efficiency,
|
|
|
|
you can pass a pointer to the array:
|
|
|
|
</p>
|
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<pre>
|
2009-09-27 18:59:36 -06:00
|
|
|
func Sum(a *[]float) (sum float) {
|
|
|
|
for _, v := range a {
|
|
|
|
sum += v
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
array := [...]float{7.0, 8.5, 9.1};
|
|
|
|
x := sum(&array); // Note the explicit address-of operator
|
2009-08-23 15:00:28 -06:00
|
|
|
</pre>
|
|
|
|
|
2009-09-27 18:59:36 -06:00
|
|
|
<p>
|
|
|
|
But even this style isn't idiomatic Go. Slices are.
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<h3 id="slices">Slices</h3>
|
|
|
|
|
|
|
|
<p>
|
2009-10-05 15:48:57 -06:00
|
|
|
Slices wrap arrays to give a more general, powerful, and convenient
|
|
|
|
interface to sequences of data. Except for items with explicit
|
|
|
|
dimension such as transformation matrices, most array programming in
|
|
|
|
Go is done with slices rather than simple arrays.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
Slices are <i>reference types</i>, which means that if you assign one
|
|
|
|
slice to another, both refer to the same underlying array. For
|
|
|
|
instance, if a function takes a slice argument, changes it makes to
|
|
|
|
the elements of the slice will be visible to the caller, analogous to
|
|
|
|
passing a pointer to the underlying array. A <code>Read</code>
|
|
|
|
function can therefore accept a slice argument rather than a (pointer
|
|
|
|
to an) array and a count; the length within the slice sets an upper
|
|
|
|
limit of how much data to read. Here is the signature of the
|
|
|
|
<code>Read</code> method of the <code>File</code> type in package
|
|
|
|
<code>os</code>:
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
func (file *File) Read(buf []byte) (n int, err os.Error)
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
The method returns the number of bytes read and an error value, if
|
|
|
|
any. To read into the first 32 bytes of a larger buffer
|
|
|
|
<code>b</code>, <i>slice</i> (here used as a verb) the buffer:
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
n, err := f.Read(buf[0:32]);
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
Such slicing is common and efficient. In fact, leaving efficiency aside for
|
|
|
|
the moment, this snippet would also read the first 32 bytes of the buffer:
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
var n int;
|
|
|
|
var err os.Error;
|
|
|
|
for i := 0; i < 32; i++ {
|
|
|
|
nbytes, e := f.Read(buf[i:i+1]);
|
|
|
|
if nbytes == 0 || e != nil {
|
|
|
|
err = e;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
n += nbytes;
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
The length of a slice may be changed as long as it still fits within
|
|
|
|
the limits of the underyling array; just assign it to a slice of
|
|
|
|
itself. The <i>capacity</i> of a slice, accessible by the built-in
|
|
|
|
function <code>cap</code>, reports the maximum length the slice may
|
|
|
|
assume. Here is a function to append data to a slice. If the data
|
|
|
|
exceeds the capacity, the slice is reallocated. The
|
|
|
|
resulting slice is returned. The function uses the fact that
|
|
|
|
<code>len</code> and <code>cap</code> are legal when applied to the
|
|
|
|
<code>nil</code> slice, and return 0.
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
func Append(slice, data[]byte) []byte {
|
|
|
|
l := len(slice);
|
|
|
|
if l + len(data) > cap(slice) { // reallocate
|
|
|
|
// Allocate double what's needed, for future growth.
|
|
|
|
newSlice := make([]byte, (l+len(data))*2);
|
|
|
|
// Copy data (could use bytes.Copy()).
|
|
|
|
for i, c := range slice {
|
|
|
|
newSlice[i] = c
|
|
|
|
}
|
|
|
|
slice = newSlice;
|
|
|
|
}
|
|
|
|
slice = slice[0:l+len(data)];
|
|
|
|
for i, c := range data {
|
|
|
|
slice[l+i] = c
|
|
|
|
}
|
|
|
|
return slice;
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
We must return the slice afterwards because, although <code>Append</code>
|
|
|
|
can modify the elements of <code>slice</code>, the slice itself (the run-time data
|
|
|
|
structure holding the pointer, length, and capacity) is passed by value.
|
2009-09-27 18:59:36 -06:00
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<h3 id="maps">Maps</h3>
|
|
|
|
<h3 id="printing">Printing</h3>
|
|
|
|
|
|
|
|
<h2>Methods</h2>
|
2009-10-05 15:48:57 -06:00
|
|
|
|
2009-09-27 18:59:36 -06:00
|
|
|
<h3 id="pointers_vs_values">Pointers vs. Values</h3>
|
2009-10-05 15:48:57 -06:00
|
|
|
<p>
|
|
|
|
Methods can be defined for any named type except pointers and interfaces;
|
|
|
|
the receiver does not have to be a struct.
|
|
|
|
<p>
|
|
|
|
In the discussion of slices above, we wrote an <code>Append</code>
|
|
|
|
function. We can define it as a method on slices instead. To do
|
|
|
|
this, we first declare a named type to which we can bind the method, and
|
|
|
|
then make the receiver for the method a value of that type.
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
type ByteSlice []byte
|
2009-09-27 18:59:36 -06:00
|
|
|
|
2009-10-05 15:48:57 -06:00
|
|
|
func (slice ByteSlice) Append(data []byte) []slice {
|
|
|
|
// Body exactly the same as above
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
This still requires the method to return the updated slice. We can
|
|
|
|
eliminate that clumsiness by redefining the method to take a
|
|
|
|
<i>pointer</i> to a <code>ByteSlice</code> as its receiver, so the
|
|
|
|
method can overwrite the caller's slice.
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
func (p *ByteSlice) Append(data []byte) {
|
|
|
|
slice := *p;
|
|
|
|
// Body as above, without the return.
|
|
|
|
*p = slice;
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
In fact, we can do even better. If we modify our function so it looks
|
|
|
|
like a standard <code>Write</code> method, like this,
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
func (p *ByteSlice) Write(data []byte) (n int, err os.Error) {
|
|
|
|
slice := *p;
|
|
|
|
// Again as above.
|
|
|
|
*p = slice;
|
|
|
|
return len(data), nil)
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
then the type <code>*ByteSlice</code> satisfies the standard interface
|
|
|
|
<code>io.Writer</code>, which is handy. For instance, we can
|
|
|
|
print into one:
|
|
|
|
</p>
|
|
|
|
<pre>
|
|
|
|
var b ByteSlice;
|
|
|
|
fmt.Fprintf(&b, "This minute has %d seconds\n", 61);
|
|
|
|
</pre>
|
|
|
|
<p>
|
|
|
|
Notice that we must pass the address of a <code>ByteSlice</code>
|
|
|
|
because only <code>*ByteSlice</code> satisfies <code>io.Writer</code>.
|
|
|
|
The rule about pointers vs. values for receivers is that value methods
|
|
|
|
can be invoked on pointers and values, but pointer methods can only be
|
|
|
|
invoked on pointers. This is because pointer methods can modify the
|
|
|
|
receiver; invoking them on a copy of the value would cause those
|
|
|
|
modifications to be discarded.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
By the way, the idea of using <code>Write</code> on a slice of bytes
|
|
|
|
is implemented by <code>bytes.Buffer</code>.
|
|
|
|
</p>
|
2009-09-27 18:59:36 -06:00
|
|
|
|
|
|
|
<h2>More to come</h2>
|
|
|
|
|
|
|
|
<!---
|
|
|
|
|
|
|
|
<h2 id="idioms">Idioms</h2>
|
|
|
|
|
|
|
|
|
2009-08-23 15:00:28 -06:00
|
|
|
<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>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<h2 id="errors">Errors</h2>
|
|
|
|
|
2009-07-31 12:41:30 -06:00
|
|
|
<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.
|
2009-10-01 15:08:00 -06:00
|
|
|
Even if there is only one failure mode now,
|
2009-07-31 12:41:30 -06:00
|
|
|
there may be more later.
|
|
|
|
</p>
|
|
|
|
|
2009-06-25 10:38:35 -06:00
|
|
|
<h3 id="error-context">Return structured errors</h3>
|
|
|
|
|
2009-08-03 15:07:19 -06:00
|
|
|
Implementations of <code>os.Error</code> should
|
|
|
|
describe the error and provide context.
|
2009-06-25 10:38:35 -06:00
|
|
|
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>
|
2009-08-03 15:07:19 -06:00
|
|
|
// 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 {
|
2009-08-13 12:29:05 -06:00
|
|
|
return e.Op + " " + e.Path + ": " + e.Error.String();
|
2009-08-03 15:07:19 -06:00
|
|
|
}
|
2009-06-25 10:38:35 -06:00
|
|
|
</pre>
|
|
|
|
|
2009-08-13 12:29:05 -06:00
|
|
|
<p>
|
2009-06-25 10:38:35 -06:00
|
|
|
<code>PathError</code>'s <code>String</code> formats
|
2009-08-03 15:07:19 -06:00
|
|
|
the error nicely, including the operation and file name
|
|
|
|
tha failed; just printing the error generates a
|
|
|
|
message, such as
|
2009-08-13 12:29:05 -06:00
|
|
|
</p>
|
2009-06-25 10:38:35 -06:00
|
|
|
<pre>
|
2009-08-03 15:07:19 -06:00
|
|
|
open /etc/passwx: no such file or directory
|
2009-06-25 10:38:35 -06:00
|
|
|
</pre>
|
2009-08-13 12:29:05 -06:00
|
|
|
<p>
|
2009-08-03 15:07:19 -06:00
|
|
|
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
|
2009-08-13 12:29:05 -06:00
|
|
|
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.
|
2009-08-03 15:07:19 -06:00
|
|
|
</p>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
<h2 id="types">Programmer-defined types</h2>
|
|
|
|
|
2009-08-19 14:24:24 -06:00
|
|
|
<p>Packages that export only a single type can
|
2009-06-25 10:38:35 -06:00
|
|
|
shorten <code>NewTypeName</code> to <code>New</code>;
|
2009-07-06 16:15:56 -06:00
|
|
|
the vector constructor is
|
2009-06-25 10:38:35 -06:00
|
|
|
<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>
|
|
|
|
|
|
|
|
|
|
|
|
<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:
|
2009-07-06 16:15:56 -06:00
|
|
|
the rest of the code is unaffected by the change of algorithm.
|
2009-06-25 10:38:35 -06:00
|
|
|
</p>
|
|
|
|
|
2009-07-06 16:15:56 -06:00
|
|
|
<h3 id="asdf">Use interface adapters to expand an implementation</h3>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
XXX
|
|
|
|
|
2009-07-06 16:15:56 -06:00
|
|
|
<h3 id="fdsa">Use anonymous fields to incorporate an implementation</h3>
|
2009-06-25 10:38:35 -06:00
|
|
|
|
|
|
|
XXX
|
|
|
|
|
|
|
|
<h2>Data-Driven Programming</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
tables
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<p>
|
2009-09-27 18:59:36 -06:00
|
|
|
XXX struct tags for marshaling.
|
2009-06-25 10:38:35 -06:00
|
|
|
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>
|
2009-08-19 14:24:24 -06:00
|
|
|
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
|
2009-06-25 10:38:35 -06:00
|
|
|
no more tests were run.
|
2009-08-19 14:24:24 -06:00
|
|
|
XXX
|
|
|
|
test bottom up
|
|
|
|
test runs top to bottom
|
|
|
|
how to use gotest
|
|
|
|
XXX
|
2009-06-25 10:38:35 -06:00
|
|
|
</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.
|
2009-10-01 15:08:00 -06:00
|
|
|
If a function returns a complex data structure,
|
2009-06-25 10:38:35 -06:00
|
|
|
<code>reflect.DeepEqual</code> combined with table-driven testing
|
2009-10-01 15:08:00 -06:00
|
|
|
makes it easy to check that the return value is
|
2009-06-25 10:38:35 -06:00
|
|
|
exactly as expected.
|
|
|
|
</p>
|
|
|
|
|
2009-08-13 12:29:05 -06:00
|
|
|
<h2 id="be-consistent">Be consistent</h2>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
Programmers often want their style to be distinctive,
|
|
|
|
writing loops backwards or using custom spacing and
|
2009-09-27 18:59:36 -06:00
|
|
|
naming conventions. Such idiosyncrasies come at a
|
2009-08-13 12:29:05 -06:00
|
|
|
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,
|
2009-10-05 15:48:57 -06:00
|
|
|
but also within the surrounding source files.
|
2009-08-13 12:29:05 -06:00
|
|
|
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>
|
|
|
|
|
2009-10-05 15:48:57 -06:00
|
|
|
<pre>
|
|
|
|
TODO
|
|
|
|
verifying implementation
|
|
|
|
type Color uint32
|
|
|
|
|
|
|
|
// Check that Color implements image.Color and image.Image
|
|
|
|
var _ image.Color = Black
|
|
|
|
var _ image.Image = Black
|
|
|
|
</pre>
|
2009-09-02 17:41:41 -06:00
|
|
|
-->
|