From: Rob Pike
gofmt
.
-Some formatting details remain. Very briefly, +Some formatting details remain. Very briefly:
if
,
+ Go needs fewer parentheses than C and Java: control structures (if
,
for
, switch
) do not have parentheses in
their syntax.
Also, the operator precedence hierarchy is shorter and clearer, so
x<<8 + y<<16- means what the spacing implies. + means what the spacing implies, unlike in the other languages.
/* */
block comments
and C++-style //
line comments.
Line comments are the norm;
-block comments appear mostly as package comments and
-are also useful to disable large swaths of code.
+block comments appear mostly as package comments, but
+are useful within an expression or to disable large swaths of code.
@@ -205,6 +211,13 @@ takes care of that.
The comments are uninterpreted plain text, so HTML and other
annotations such as _this_
will reproduce verbatim and should
not be used.
+One adjustment godoc
does do is to display indented
+text in a fixed-width font, suitable for program snippets.
+The package comment for the
+fmt
package uses this to good effect.
+
Depending on the context, godoc
might not even
reformat comments, so make sure they look good straight up:
use correct spelling, punctuation, and sentence structure,
@@ -231,6 +244,33 @@ starts with the name being declared.
func Compile(str string) (regexp *Regexp, err error) {
+
+If the name always begins the comment, the output of godoc
+can usefully be run through grep
.
+Imagine you couldn't remember the name "Compile" but were looking for
+the parsing function for regular expressions, so you ran
+the command,
+
+$ godoc regexp | grep parse ++ +
+If all the doc comments in the package began, "This function...", grep
+wouldn't help you remember the name. But because the package starts each
+doc comment with the name, you'd see something like this,
+which recalls the word you're looking for.
+
+$ godoc regexp | grep parse + Compile parses a regular expression and returns, if successful, a Regexp + parsed. It simplifies safe initialization of global variables holding + cannot be parsed. It simplifies safe initialization of global variables +$ ++
Go's declaration syntax allows grouping of declarations. A single doc comment can introduce a group of related constants or variables. @@ -265,7 +305,7 @@ var (
Names are as important in Go as in any other language.
-In some cases they even have semantic effect: for instance,
+They even have semantic effect:
the visibility of a name outside a package is determined by whether its
first character is upper case.
It's therefore worth spending a little time talking about naming conventions
@@ -310,11 +350,11 @@ not encoding_base64
and not encodingBase64
.
-The importer of a package will use the name to refer to its contents
-(the import .
notation is intended mostly for tests and other
-unusual situations and should be avoided unless necessary),
+The importer of a package will use the name to refer to its contents.
so exported names in the package can use that fact
to avoid stutter.
+(Don't use the import .
notation, which can simplify
+tests that must run outside the package they are testing, but should otherwise be avoided.)
For instance, the buffered reader type in the bufio
package is called Reader
,
not BufReader
, because users see it as bufio.Reader
,
which is a clear, concise name.
@@ -335,9 +375,7 @@ Another short example is once.Do
;
once.Do(setup)
reads well and would not be improved by
writing once.DoOrWaitUntilDone(setup)
.
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.
+A helpful doc comment can often be more valuable than an extra long name.
-Like C, Go's formal grammar uses semicolons to terminate statements; -unlike C, those semicolons do not appear in the source. +Like C, Go's formal grammar uses semicolons to terminate statements, +but unlike in C, those semicolons do not appear in the source. Instead the lexer uses a simple rule to insert semicolons automatically as it scans, so the input text is mostly free of them.
@@ -431,7 +469,8 @@ statements on a line, should you write code that way.
-One caveat. You should never put the opening brace of a
+One consequence of the semicolon insertion rules
+is that you cannot put the opening brace of a
control structure (if
, for
, switch
,
or select
) on the next line. If you do, a semicolon
will be inserted before the brace, which could cause unwanted
@@ -540,7 +579,7 @@ codeUsing(f, d)
-
An aside: The last example in the previous section demonstrates a detail of how the @@ -577,7 +616,7 @@ if it has already been declared, provided:
v
-(if v
is already declared in an outer scope, the declaration will create a new variable),v
is already declared in an outer scope, the declaration will create a new variable §),
v
, andif-else
chain.
You'll see it used often.
++§ It's worth noting here that in Go the scope of function parameters and return values +is the same as the function body, even though they appear lexically outside the braces +that enclose the body. +
+@@ -634,7 +679,7 @@ If you only need the first item in the range (the key or index), drop the second
for key := range m { - if expired(key) { + if key.expired() { delete(m, key) } } @@ -652,29 +697,30 @@ for _, value := range array {For strings, the
range
does more work for you, breaking out individual -Unicode characters by parsing the UTF-8. +Unicode code points by parsing the UTF-8. Erroneous encodings consume one byte and produce the replacement rune U+FFFD. The loop-for pos, char := range "æ¥æ¬èª" { - fmt.Printf("character %c starts at byte position %d\n", char, pos) +for pos, char := range "æ¥æ¬\x80èª" { // \x80 is an illegal UTF-8 encoding + fmt.Printf("character %#U starts at byte position %d\n", char, pos) }prints
-character æ¥ starts at byte position 0 -character æ¬ starts at byte position 3 -character èª starts at byte position 6 +character U+65E5 'æ¥' starts at byte position 0 +character U+672C 'æ¬' starts at byte position 3 +character U+FFFD '�' starts at byte position 6 +character U+8A9E 'èª' starts at byte position 7Finally, Go has no comma operator and
++
and--
are statements not expressions. Thus if you want to run multiple variables in afor
-you should use parallel assignment. +you should use parallel assignment (although that precludes++
and--
).// Reverse a @@ -757,19 +803,23 @@ variable. Such a type switch uses the syntax of a type assertion with the keywordtype
inside the parentheses. If the switch declares a variable in the expression, the variable will have the corresponding type in each clause. +It's also idiomatic to reuse the name in such cases, in effect declaring +a new variable with the same name but a different type in each case.-switch t := interfaceValue.(type) { +var t interface{} +t = functionOfSomeType() +switch t := t.(type) { default: - fmt.Printf("unexpected type %T", t) // %T prints type + fmt.Printf("unexpected type %T", t) // %T prints whatever type t has case bool: - fmt.Printf("boolean %t\n", t) + fmt.Printf("boolean %t\n", t) // t has type bool case int: - fmt.Printf("integer %d\n", t) + fmt.Printf("integer %d\n", t) // t has type int case *bool: - fmt.Printf("pointer to boolean %t\n", *t) + fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool case *int: - fmt.Printf("pointer to integer %d\n", *t) + fmt.Printf("pointer to integer %d\n", *t) // t has type *int }