diff options
Diffstat (limited to 'doc/effective_go.html')
-rw-r--r-- | doc/effective_go.html | 351 |
1 files changed, 282 insertions, 69 deletions
diff --git a/doc/effective_go.html b/doc/effective_go.html index 6cacac630..e02694add 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -41,8 +41,14 @@ 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. +Moreover, many of the packages contain working, self-contained +executable examples you can run directly from the +<a href="http://golang.org">golang.org</a> web site, such as +<a href="http://golang.org/pkg/strings/#example_Map">this one</a> (click +on the word "Example" to open it up). If you have a question about how to approach a problem or how something -might be implemented, they can provide answers, ideas and +might be implemented, the documentation, code and examples in the +library can provide answers, ideas and background. </p> @@ -108,7 +114,7 @@ All Go code in the standard packages has been formatted with <code>gofmt</code>. <p> -Some formatting details remain. Very briefly, +Some formatting details remain. Very briefly: </p> <dl> @@ -123,14 +129,14 @@ Some formatting details remain. Very briefly, </dd> <dt>Parentheses</dt> <dd> - Go needs fewer parentheses: control structures (<code>if</code>, + Go needs fewer parentheses than C and Java: 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. + means what the spacing implies, unlike in the other languages. </dd> </dl> @@ -140,8 +146,8 @@ x<<8 + y<<16 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. +block comments appear mostly as package comments, but +are useful within an expression or to disable large swaths of code. </p> <p> @@ -167,10 +173,9 @@ should set up the detailed documentation that follows. <pre> /* - Package regexp implements a simple library for - regular expressions. +Package regexp implements a simple library for regular expressions. - The syntax of the regular expressions accepted is: +The syntax of the regular expressions accepted is: regexp: concatenation { '|' concatenation } @@ -206,6 +211,13 @@ takes care of that. 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. +One adjustment <code>godoc</code> does do is to display indented +text in a fixed-width font, suitable for program snippets. +The package comment for the +<a href="http://golang.org/pkg/fmt/"><code>fmt</code> package</a> uses this to good effect. +</p> + +<p> Depending on the context, <code>godoc</code> might not even reformat comments, so make sure they look good straight up: use correct spelling, punctuation, and sentence structure, @@ -233,6 +245,33 @@ func Compile(str string) (regexp *Regexp, err error) { </pre> <p> +If the name always begins the comment, the output of <code>godoc</code> +can usefully be run through <code>grep</code>. +Imagine you couldn't remember the name "Compile" but were looking for +the parsing function for regular expressions, so you ran +the command, +</p> + +<pre> +$ godoc regexp | grep parse +</pre> + +<p> +If all the doc comments in the package began, "This function...", <code>grep</code> +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. +</p> + +<pre> +$ 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 +$ +</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. @@ -266,7 +305,7 @@ var ( <p> 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 @@ -311,11 +350,11 @@ not <code>encoding_base64</code> and not <code>encodingBase64</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 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 <code>import .</code> 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 <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. @@ -336,9 +375,7 @@ 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. +A helpful doc comment can often be more valuable than an extra long name. </p> <h3 id="Getters">Getters</h3> @@ -395,8 +432,8 @@ multiword names. <h2 id="semicolons">Semicolons</h2> <p> -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. </p> @@ -432,7 +469,8 @@ statements on a line, should you write code that way. </p> <p> -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 (<code>if</code>, <code>for</code>, <code>switch</code>, or <code>select</code>) on the next line. If you do, a semicolon will be inserted before the brace, which could cause unwanted @@ -541,7 +579,7 @@ codeUsing(f, d) </pre> -<h3 id="redeclaration">Redeclaration</h3> +<h3 id="redeclaration">Redeclaration and reassignment</h3> <p> An aside: The last example in the previous section demonstrates a detail of how the @@ -578,7 +616,7 @@ if it has already been declared, provided: <ul> <li>this declaration is in the same scope as the existing declaration of <code>v</code> -(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable),</li> +(if <code>v</code> is already declared in an outer scope, the declaration will create a new variable §),</li> <li>the corresponding value in the initialization is assignable to <code>v</code>, and</li> <li>there is at least one other variable in the declaration that is being declared anew.</li> </ul> @@ -590,6 +628,12 @@ in a long <code>if-else</code> chain. You'll see it used often. </p> +<p> +§ 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. +</p> + <h3 id="for">For</h3> <p> @@ -635,7 +679,7 @@ If you only need the first item in the range (the key or index), drop the second </p> <pre> for key := range m { - if expired(key) { + if key.expired() { delete(m, key) } } @@ -653,29 +697,30 @@ for _, value := range array { <p> For strings, the <code>range</code> 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 </p> <pre> -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) } </pre> <p> prints </p> <pre> -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 7 </pre> <p> Finally, Go has no comma operator and <code>++</code> and <code>--</code> are statements not expressions. Thus if you want to run multiple variables in a <code>for</code> -you should use parallel assignment. +you should use parallel assignment (although that precludes <code>++</code> and <code>--</code>). </p> <pre> // Reverse a @@ -714,6 +759,7 @@ func unhex(c byte) byte { <p> There is no automatic fall through, but cases can be presented in comma-separated lists. +</p> <pre> func shouldEscape(c byte) bool { switch c { @@ -725,10 +771,11 @@ func shouldEscape(c byte) bool { </pre> <p> -Here's a comparison routine for byte arrays that uses two +Here's a comparison routine for byte slices that uses two <code>switch</code> statements: +</p> <pre> -// Compare returns an integer comparing the two byte arrays, +// Compare returns an integer comparing the two byte slices, // lexicographically. // The result will be 0 if a == b, -1 if a < b, and +1 if a > b func Compare(a, b []byte) int { @@ -756,19 +803,23 @@ variable. Such a <em>type switch</em> uses the syntax of a type assertion with the keyword <code>type</code> 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. </p> <pre> -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 } </pre> @@ -808,7 +859,7 @@ This is a common style; see the section on error handling for more examples. A similar approach obviates the need to pass a pointer to a return value to simulate a reference parameter. Here's a simple-minded function to -grab a number from a position in a byte array, returning the number +grab a number from a position in a byte slice, returning the number and the next position. </p> @@ -825,12 +876,12 @@ func nextInt(b []byte, i int) (int, int) { </pre> <p> -You could use it to scan the numbers in an input array <code>a</code> like this: +You could use it to scan the numbers in an input slice <code>b</code> like this: </p> <pre> - for i := 0; i < len(a); { - x, i = nextInt(a, i) + for i := 0; i < len(b); { + x, i = nextInt(b, i) fmt.Println(x) } </pre> @@ -1180,6 +1231,7 @@ structure with length 10 and a capacity of 100 pointing at the first 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> <p> These examples illustrate the difference between <code>new</code> and @@ -1330,6 +1382,8 @@ func Append(slice, data[]byte) []byte { 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. +</p> + <p> The idea of appending to a slice is so useful it's captured by the <code>append</code> built-in function. To understand that function's @@ -1369,8 +1423,8 @@ var timeZone = map[string] int { </pre> <p> Assigning and fetching map values looks syntactically just like -doing the same for arrays except that the index doesn't need to -be an integer. +doing the same for arrays and slices except that the index doesn't +need to be an integer. </p> <pre> offset := timeZone["EST"] @@ -1495,7 +1549,7 @@ prints If you just want the default conversion, such as decimal for integers, you can use the catchall format <code>%v</code> (for “value”); the result is exactly what <code>Print</code> and <code>Println</code> would produce. -Moreover, that format can print <em>any</em> value, even arrays, structs, and +Moreover, that format can print <em>any</em> value, even arrays, slices, structs, and maps. Here is a print statement for the time zone map defined in the previous section. </p> <pre> @@ -1539,12 +1593,13 @@ map[string] int{"CST":-21600, "PST":-28800, "EST":-18000, "UTC":0, "MST":-25200} That quoted string format is also available through <code>%q</code> when applied to a value of type <code>string</code> or <code>[]byte</code>; the alternate format <code>%#q</code> will use backquotes instead if possible. -Also, <code>%x</code> works on strings and arrays of bytes as well as on integers, -generating a long hexadecimal string, and with +Also, <code>%x</code> works on strings, byte arrays and byte slices as well as +on integers, generating a long hexadecimal string, and with a space in the format (<code>% x</code>) it puts spaces between the bytes. </p> <p> Another handy format is <code>%T</code>, which prints the <em>type</em> of a value. +</p> <pre> fmt.Printf("%T\n", timeZone) </pre> @@ -1606,6 +1661,7 @@ func Println(v ...interface{}) { We write <code>...</code> after <code>v</code> in the nested call to <code>Sprintln</code> to tell the compiler to treat <code>v</code> as a list of arguments; otherwise it would just pass <code>v</code> as a single slice argument. +</p> <p> There's even more to printing than we've covered here. See the <code>godoc</code> documentation for package <code>fmt</code> for the details. @@ -1738,9 +1794,9 @@ initializer can be a general expression computed at run time. </p> <pre> var ( - HOME = os.Getenv("HOME") - USER = os.Getenv("USER") - GOROOT = os.Getenv("GOROOT") + home = os.Getenv("HOME") + user = os.Getenv("USER") + goRoot = os.Getenv("GOROOT") ) </pre> @@ -1763,17 +1819,17 @@ correctness of the program state before real execution begins. <pre> func init() { - if USER == "" { + if user == "" { log.Fatal("$USER not set") } - if HOME == "" { - HOME = "/usr/" + USER + if home == "" { + home = "/home/" + user } - if GOROOT == "" { - GOROOT = HOME + "/go" + if goRoot == "" { + goRoot = home + "/go" } - // GOROOT may be overridden by --goroot flag on command line. - flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory") + // goRoot may be overridden by --goroot flag on command line. + flag.StringVar(&goRoot, "goroot", goRoot, "Go root directory") } </pre> @@ -1783,6 +1839,7 @@ func init() { <p> Methods can be defined for any named type that is not a pointer or an interface; the receiver does not have to be a struct. +</p> <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 @@ -2012,6 +2069,7 @@ Those methods include the standard <code>Write</code> method, so an can be used. <code>Request</code> is a struct containing a parsed representation of the request from the client. +</p> <p> For brevity, let's ignore POSTs and assume HTTP requests are always GETs; that simplification does not affect the way the handlers are @@ -2034,6 +2092,7 @@ func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) { (Keeping with our theme, note how <code>Fprintf</code> can print to an <code>http.ResponseWriter</code>.) For reference, here's how to attach such a server to a node on the URL tree. +</p> <pre> import "net/http" ... @@ -2187,6 +2246,7 @@ what a <code>Reader</code> does <em>and</em> what a <code>Writer</code> does; it is a union of the embedded interfaces (which must be disjoint sets of methods). Only interfaces can be embedded within interfaces. +</p> <p> The same basic idea applies to structs, but with more far-reaching implications. The <code>bufio</code> package has two struct types, @@ -2378,10 +2438,11 @@ exits, silently. (The effect is similar to the Unix shell's background.) </p> <pre> -go list.Sort() // run list.Sort concurrently; don't wait for it. +go list.Sort() // run list.Sort concurrently; don't wait for it. </pre> <p> A function literal can be handy in a goroutine invocation. +</p> <pre> func Announce(message string, delay time.Duration) { go func() { @@ -2393,6 +2454,7 @@ func Announce(message string, delay time.Duration) { <p> In Go, function literals are closures: the implementation makes sure the variables referred to by the function survive as long as they are active. +</p> <p> These examples aren't too practical because the functions have no way of signaling completion. For that, we need channels. @@ -2425,7 +2487,7 @@ c := make(chan int) // Allocate a channel. // Start the sort in a goroutine; when it completes, signal on the channel. go func() { list.Sort() - c <- 1 // Send a signal; value does not matter. + c <- 1 // Send a signal; value does not matter. }() doSomethingForAWhile() <-c // Wait for sort to finish; discard sent value. @@ -2494,6 +2556,7 @@ One of the most important properties of Go is that a channel is a first-class value that can be allocated and passed around like any other. A common use of this property is to implement safe, parallel demultiplexing. +</p> <p> In the example in the previous section, <code>handle</code> was an idealized handler for a request but we didn't define the @@ -2822,7 +2885,7 @@ func init() { <p> When <code>panic</code> is called, including implicitly for run-time -errors such as indexing an array out of bounds or failing a type +errors such as indexing a slice out of bounds or failing a type assertion, it immediately stops execution of the current function and begins unwinding the stack of the goroutine, running any deferred functions along the way. If that unwinding reaches the top of the @@ -2923,7 +2986,7 @@ that it has the local type <code>Error</code>. If it does not, the type assertion will fail, causing a run-time error that continues the stack unwinding as though nothing had interrupted it. This check means that if something unexpected happens, such -as an array index out of bounds, the code will fail even though we +as an index out of bounds, the code will fail even though we are using <code>panic</code> and <code>recover</code> to handle user-triggered errors. </p> @@ -2952,6 +3015,155 @@ filter unexpected problems and re-panic with the original error. That's left as an exercise for the reader. </p> +<h2 id="blank">Blank identifier</h2> + +<p> +Go defines a special identifier <code>_</code>, called the <i>blank identifier</i>. +The blank identifier can be used in a declaration to avoid +declaring a name, and it can be used in an assignment to discard a value. +This definition makes it useful in a variety of contexts. +</p> + +<h3 id="blank_assign">Multiple assignment</h3> + +<p> +If an assignment requires multiple values on the left side, +but one of the values will not be used by the program, +using the blank identifier in the assignment avoids the need +to create a dummy variable. +We saw one example of this in the discussion of +<a href="#for">for loops</a> above. +</p> +<pre> +sum := 0 +for _, value := range array { + sum += value +} +</pre> + +<p> +Another common use is when calling a function that returns +a value and an error, but only the error is important. +</p> +<pre> +if _, err := os.Stat(path); os.IsNotExist(err) { + fmt.Printf("%s does not exist\n", path) +} +</pre> + +<p> +A final use that is more common than it should be is to +discard the error from a function that is not expected to fail. +This is usually a mistake: when the function does fail, the code +will continue on and probably panic dereferencing a nil pointer. +</p> +<pre> +// Always check errors: this program crashes if path does not exist. +fi, _ := os.Stat(path) +fmt.Printf("%s is %d bytes\n", path, fi.Size()) +</pre> + +<h3 id="blank_unused">Unused imports and variables</h3> + +<p> +Go defines that it is an error to import a package without using it, +or to declare a variable without using its value. +Unused imports bloat a program and lengthen compiles unnecessarily; +a variable that is initialized but not used is at least +a wasted computation and perhaps indicative of a +larger bug. +Of course, both of these situations also arise in programs +that are under active development, as you test and refine +your code. +</p> +<p> +For example, in this program, there are two unused imports +(<code>fmt</code> and <code>io</code>) +and an unused variable (<code>greeting</code>). +</p> +{{code "/doc/progs/unused1.go" `/package/` `$`}} +<p> +Top-level blank declarations referring to the packages +will silence the unused import errors. +By convention, these declarations should come immediately after +the imports, as a reminder to clean things up later. +Similarly, assigning <code>greeting</code> to a blank identifier +will silence the unused variable error. +</p> +{{code "/doc/progs/unused2.go" `/package/` `$`}} + +<h3 id="blank_import">Import for side effect</h3> + +<p> +An unused import like <code>fmt</code> or <code>io</code> in the last section +should eventually be used or removed: +blank assignments identify code as a work in progress. +But sometimes it is useful to import a package only for its +side effects, without any explicit use. +For example, during its <code>init</code> function, +the <code><a href="/pkg/net/http/pprof/">net/http/pprof</a></code> +package registers HTTP handlers that provide useful +debugging information. It has an exported API too, but +most clients need only the handler registration. +In this situation, it is conventional to rename the package +to the blank identifier: +</p> +<pre> +import _ "net/http/pprof" +</pre> +<p> +This form of import makes clear that the package is being +imported for its side effects, because there is no other possible +use of the package: in this file, it doesn't have a name. +</p> + +<h3 id="blank_implements">Interface checks</h3> + +<p> +As we saw in the discussion of <a href="#interfaces_and_types">interfaces</a> above, +Go does not require a type to declare explicitly that it implements an interface. +It implements the interface by simply implementing the required methods. +This makes Go programs more lightweight and flexible, and it can avoid +unnecessary dependencies between packages. +Most interface conversions are static, visible to the compiler, +and therefore checked at compile time. +For example, passing an <code>*os.File</code> to a function +expecting an <code>io.Reader</code> will not compile unless +<code>*os.File</code> implements the <code>io.Reader</code> interface. +</p> +<p> +However, some types that are used only to satisfy dynamic interface checks. +For example, the <code><a href="/pkg/encoding/json/">encoding/json</a></code> +package defines a <code><a href="/pkg/encoding/json/#Marshaler">Marshaler</a></code> +interface. If the JSON encoder encounters a type implementing that interface, +the encoder will let the type convert itself to JSON instead of using the standard +conversion. +This check is done only at runtime, with code like: +</p> +<pre> +m, ok := val.(json.Marshaler) +</pre> +<p> +If a type—for example, +<code><a href="/pkg/encoding/json/#RawMessage">json.RawMessage</a></code>—intends +to customize its JSON representation, it should implement +<code>json.Marshaler</code>, but there are no static conversions that would +cause the compiler to verify this automatically. +A declaration can be used to add such a check: +</p> +<pre> +var _ json.Marshaler = (*RawMessage)(nil) +</pre> +<p> +As part of type-checking this static assignment of a +<code>*RawMessage</code> to a <code>Marshaler</code>, +the Go compiler will require that <code>*RawMessage</code> implements <code>Marshaler</code>. +Using the blank identifier here indicates that +the declaration exists only for the type checking, +not to create a variable. +Conventionally, such declarations are used only when there are +no static conversions already present in the code. +</p> <h2 id="web_server">A web server</h2> @@ -2973,7 +3185,7 @@ for instance, a URL, saving you typing the URL into the phone's tiny keyboard. Here's the complete program. An explanation follows. </p> -{{code "/doc/progs/eff_qr.go"}} +{{code "/doc/progs/eff_qr.go" `/package/` `$`}} <p> The pieces up to <code>main</code> should be easy to follow. The one flag sets a default HTTP port for our server. The template @@ -2992,11 +3204,11 @@ server; it blocks while the server runs. executes the template on the data in the form value named <code>s</code>. </p> <p> -The template package is powerful; +The template package <code>html/template</code> is powerful; this program just touches on its capabilities. -In essence, it rewrites a piece of text on the fly by substituting elements derived +In essence, it rewrites a piece of HTML text on the fly by substituting elements derived from data items passed to <code>templ.Execute</code>, in this case the -form value. +form value. Within the template text (<code>templateStr</code>), double-brace-delimited pieces denote template actions. The piece from <code>{{html "{{if .}}"}}</code> @@ -3005,13 +3217,14 @@ is non-empty. That is, when the string is empty, this piece of the template is suppressed. </p> <p> -The snippet <code>{{html "{{urlquery .}}"}}</code> says to process the data with the function -<code>urlquery</code>, which sanitizes the query string -for safe display on the web page. +The two snippets <code>{{html "{{.}}"}}</code> say to show the data presented to +the template—the query string—on the web page. +The HTML template package automatically provides appropriate escaping so the +text is safe to display. </p> <p> The rest of the template string is just the HTML to show when the page loads. -If this is too quick an explanation, see the <a href="/pkg/text/template/">documentation</a> +If this is too quick an explanation, see the <a href="/pkg/html/template/">documentation</a> for the template package for a more thorough discussion. </p> <p> @@ -3025,7 +3238,7 @@ TODO <pre> verifying implementation type Color uint32 - + // Check that Color implements image.Color and image.Image var _ image.Color = Black var _ image.Image = Black |