From 9dfe40441ec58c1d18e87a544fcdb98b342553c2 Mon Sep 17 00:00:00 2001
From: Rob Pike
-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
+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.
+
+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.
+
+For obvious reasons this is called the “comma ok” idiom.
+In this example, if
+To test for presence in the map without worrying about the actual value,
+you can use the blank identifier, a simple underscore (
+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.
+
+Formatted printing in Go uses a style similar to C's
+You don't need to provide a format string. For each of
+Recall that
+Here things start to diverge from C. First, the numeric formats such as
+prints
+
+If you just want the default conversion, such as decimal for integers, you can use
+the catchall format
+which gives output
+
+For maps the keys may be output in any order, of course.
+When printing a struct, the modified format
+prints
+
+(Note the ampersands.)
+That quoted string format is also available through
+Another handy format is
+prints
+
+If you want to control the default format for a custom type, all that's required is to define
+a method
+to print in the format
+
+Our
+Within the function
+There's even more to printing than we've covered here. See the Introduction
@@ -34,7 +34,7 @@ should read first.
Examples
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
+
+
+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,
+}
+
+
+var seconds int;
+var ok bool;
+seconds, ok = timeZone[tz]
+
+tz
is present, seconds
+will be set appropriately and ok
will be true; if not,
+seconds
will be set to zero and ok
will
+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;
+}
+
+_
).
+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];
+
+
+timeZone["PDT"] = 0, false; // Now on Standard Time
+
Printing
+printf
+family but is richer and more general. The functions live in the fmt
+package and have capitalized names: fmt.Printf
, fmt.Fprintf
,
+fmt.Sprintf
and so on. The string functions (Sprintf
etc.)
+return a string rather than filling in a provided buffer.
+Printf
,
+fmt.Fprintf
and fmt.Sprintf
there is another pair
+of functions, for instance Print
and Println
.
+These functions do not take a format string but instead generate a default
+format for each argument. The ln
version 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));
+
+fmt.Fprint
and friends take as a first argument any object
+that implements the io.Writer
interface; the variables os.Stdout
+and os.Stderr
are familiar instances.
+%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));
+
+
+18446744073709551615 ffffffffffffffff; -1 -1
+
+%v
(for “value”); the result is exactly
+what Print
and Println
would 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);
+
+
+map[CST:-21600 PST:-28800 EST:-18000 UTC:0 MST:-25200]
+
+%+v
annotates the
+fields of the structure with their names, and for any value the alternate
+format %#v
prints 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);
+
+
+&{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}
+
+%q
when
+applied to a value of type string
or []byte
;
+the alternate format %#q
will use backquotes instead if possible.
+Also, %x
works 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.
+%T
, which prints the type of a value.
+
+fmt.Printf("%T\n", timeZone);
+
+
+map[string] int
+
+String() string
on the type. (Methods are the subject of the next
+section.) For our simple type T
, 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);
+
+
+7/-2.35/"abc\tdef"
+
+String()
method is able to call Sprintf
because 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 of Printf
uses 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) {
+
+Printf
, v
is a variable that can be passed,
+for instance, to another print routine. Here is the implementation of the
+function log.Stderr
we used above. It passes its arguments directly to
+fmt.Sprintln
for 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)
+}
+
+godoc
documentation
+for package fmt
for 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 of os.Error
should
describe the error and provide context.
For example, os.Open
returns an os.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. -- 2.48.1