diff --git a/doc/effective_go.html b/doc/effective_go.html index af1febe2c8..ec40ce87ab 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -1,6 +1,6 @@ - +
-The Go package sources +The Go package sources are intended to serve not only as the core library but also as examples of how to use the language. @@ -97,7 +97,6 @@ type T struct {
All code in the libraries has been formatted with gofmt.
-TODO
gofmt emits them by default.
- Use spaces if you must.
+ Use spaces only if you must.
if,
- for, switch) do not have parentheses in
+ for, switch) do not require parentheses in
their syntax.
Also, the operator precedence hierarchy is shorter and clearer, so
@@ -1059,8 +1058,231 @@ structure holding the pointer, length, and capacity) is passed by value.Maps
+ ++Maps are a convenient and powerful built-in data structure to associate +values of different types. +The key can be of type that implements equality, such as integers, +floats, strings, pointers, and interfaces (as long as the dynamic type +supports equality), but not structs, arrays or slices +because those types do not have equality defined upon them. +Like slices, maps are a reference type. If you pass a map to a function +that changes the contents of the map, the changes will be visible +in the caller. +
++Maps can be constructed using the usual composite literal syntax +with colon-separated key-value pairs, +so it's easy to build them during initialization. +
++var timeZone = map[string] int { + "UTC": 0*60*60, + "EST": -5*60*60, + "CST": -6*60*60, + "MST": -7*60*60, + "PST": -8*60*60, +} +++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. An attempt to fetch a map value with a key that +is not present in the map will cause the program to crash, but +there is a way to do so safely using a multiple assignment. +
++var seconds int; +var ok bool; +seconds, ok = timeZone[tz] +++For obvious reasons this is called the “comma ok” idiom. +In this example, if
+tzis present,seconds+will be set appropriately andokwill be true; if not, +secondswill be set to zero andokwill +be false. +Here's a function that puts it together: ++func offset(tz string) int { + if seconds, ok := timeZone[tz]; ok { + return seconds + } + log.Stderr("unknown time zone", tz); + return 0; +} +++To test for presence in the map without worrying about the actual value, +you can use the blank identifier, a simple underscore (
+_). +The blank identifier can be assigned or declared with any value of any type, with the +value discarded harmlessly. For testing presence in a map, use the blank +identifier in place of the usual variable for the value. ++_, present := timeZone[tz]; +++To delete a map entry, turn the multiple assignment around by placing +an extra boolean on the right; if the boolean is false, the entry +is deleted. It's safe to do this even if the key is already absent +from the map. +
++timeZone["PDT"] = 0, false; // Now on Standard Time +Printing
++Formatted printing in Go uses a style similar to C's
+printf+family but is richer and more general. The functions live in thefmt+package and have capitalized names:fmt.Printf,fmt.Fprintf, +fmt.Sprintfand so on. The string functions (Sprintfetc.) +return a string rather than filling in a provided buffer. ++You don't need to provide a format string. For each of
+Printf, +fmt.Fprintfandfmt.Sprintfthere is another pair +of functions, for instancePrintln. +These functions do not take a format string but instead generate a default +format for each argument. Thelnversion also inserts a blank +between arguments if neither is a string and appends a newline to the output. +In this example each line produces the same output. ++fmt.Printf("Hello %d\n", 23); +fmt.Fprint(os.Stdout, "Hello ", 23, "\n"); +fmt.Println(fmt.Sprint("Hello ", 23)); +++Recall that
+fmt.Fprintand friends take as a first argument any object +that implements theio.Writerinterface; the variablesos.Stdout+andos.Stderrare familiar instances. ++Here things start to diverge from C. First, the numeric formats such as
+%d+do not take flags for signedness or size; instead, the printing routines use the +type of the argument to decide these properties. ++var x uint64 = 1<<64 - 1; +fmt.Printf("%d %x; %d %x\n", x, x, int64(x), int64(x)); +++prints +
++18446744073709551615 ffffffffffffffff; -1 -1 +++If you just want the default conversion, such as decimal for integers, you can use +the catchall format
+%v(for “value”); the result is exactly +whatPrintlnwould produce. +Moreover, that format can print any value, even arrays, structs, and +maps. Here is a print statement for the time zone map defined in the previous section. ++fmt.Printf("%v\n", timeZone); // or just fmt.Println(timeZone); +++which gives output +
++map[CST:-21600 PST:-28800 EST:-18000 UTC:0 MST:-25200] +++For maps the keys may be output in any order, of course. +When printing a struct, the modified format
+%+vannotates the +fields of the structure with their names, and for any value the alternate +format%#vprints the value in full Go syntax. ++type T struct { + a int; + b float; + c string; +} +t := &T{ 7, -2.35, "abc\tdef" }; +fmt.Printf("%v\n", t); +fmt.Printf("%+v\n", t); +fmt.Printf("%#v\n", t); +fmt.Printf("%#v\n", timeZone); +++prints +
++&{7 -2.35 abc def} +&{a:7 b:-2.35 c:abc def} +&main.T{a:7, b:-2.35, c:"abc\tdef"} +map[string] int{"CST":-21600, "PST":-28800, "EST":-18000, "UTC":0, "MST":-25200} +++(Note the ampersands.) +That quoted string format is also available through
+%qwhen +applied to a value of typestringor[]byte; +the alternate format%#qwill use backquotes instead if possible. +Also,%xworks on strings and arrays of bytes as well as on integers, +generating a long hexadecimal string, and with +a space in the format (% x) it puts spaces between the bytes. ++Another handy format is
%T, which prints the type of a value. ++fmt.Printf("%T\n", timeZone); +++prints +
++map[string] int +++If you want to control the default format for a custom type, all that's required is to define +a method
+String() stringon the type. (Methods are the subject of the next +section.) For our simple typeT, that might look like this. ++func (t *T) String() string { + return fmt.Sprintf("%d/%g/%q", t.a, t.b, t.c); +} +fmt.Printf("%v\n", t); +++to print in the format +
++7/-2.35/"abc\tdef" +++Our
+String()method is able to callSprintfbecause the +print routines are fully reentrant and can be used recursively. +We can even go one step further and pass a print routine's arguments directly to another such routine. +The signature ofPrintfuses the...+type for its final argument to specify that an arbitrary number of parameters can appear +after the format. ++func Printf(format string, v ...) (n int, errno os.Error) { +++Within the function
+Printf,vis a variable that can be passed, +for instance, to another print routine. Here is the implementation of the +functionlog.Stderrwe used above. It passes its arguments directly to +fmt.Sprintlnfor the actual formatting. ++// Stderr is a helper function for easy logging to stderr. It is analogous to Fprint(os.Stderr). +func Stderr(v ...) { + stderr.Output(2, fmt.Sprintln(v)); // Output takes parameters (int, string) +} +++There's even more to printing than we've covered here. See the
+godocdocumentation +for packagefmtfor the details. +Methods
Pointers vs. Values
@@ -1112,7 +1334,7 @@ print into one:var b ByteSlice; - fmt.Fprintf(&b, "This minute has %d seconds\n", 61); + fmt.Fprintf(&b, "This hour has %d days\n", 7);Notice that we must pass the address of a
ByteSlice@@ -1159,7 +1381,7 @@ Implementations ofos.Errorshould describe the error and provide context. For example,os.Openreturns anos.PathError: -/src/pkg/os/file.go: +http://go/godoc/src/pkg/os/file.go:// PathError records an error and the operation and // file path that caused it.