From f8284b64cecf38338cf62ddc6398c0a9fe655326 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 22 Jan 2013 14:00:10 -0500 Subject: [PATCH] doc/effective_go.html: add a section about the blank identifier R=golang-dev, minux.ma, bradfitz, adg CC=golang-dev https://golang.org/cl/7134056 --- doc/effective_go.html | 150 ++++++++++++++++++++++++++++++++++++++++++ doc/progs/unused1.go | 12 ++++ doc/progs/unused2.go | 16 +++++ 3 files changed, 178 insertions(+) create mode 100644 doc/progs/unused1.go create mode 100644 doc/progs/unused2.go diff --git a/doc/effective_go.html b/doc/effective_go.html index f7b07b02e3..1363f092f1 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -2966,6 +2966,156 @@ filter unexpected problems and re-panic with the original error. That's left as an exercise for the reader.

+

Blank identifier

+ +

+Go defines a special identifier _, called the blank identifier. +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. +

+ +

Multiple assignment

+ +

+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 +for loops above. +

+
+sum := 0
+for _, value := range array {
+    sum += value
+}
+
+ +

+Another common use is when calling a function that returns +a value and an error, but only the error is important. +

+
+if _, err := os.Stat(path); os.IsNotExist(err) {
+	fmt.Printf("%s does not exist\n", path)
+}
+
+ +

+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. +

+
+// 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())
+
+ +

Unused imports and variables

+ +

+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. +

+

+For example, in this program, there are two unused imports +(fmt and io) +and an unused variable (greeting). +

+{{code "/doc/progs/unused1.go" `/package/` `$`}} +

+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 greeting to a blank identifier +will silence the unused variable error. +

+{{code "/doc/progs/unused2.go" `/package/` `$`}} +

+ +

Import for side effect

+ +

+An unused import like fmt or io 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 init function, +the net/http/pprof +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: +

+
+import _ "net/http/pprof"
+
+

+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. +

+ +

Interface checks

+ +

+As we saw in the discussion of interfaces 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 *os.File to a function +expecting an io.Reader will not compile unless +*os.File implements the io.Reader interface. +

+

+However, some types that are used only to satisfy dynamic interface checks. +For example, the encoding/json +package defines a Marshaler +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: +

+
+m, ok := val.(json.Marshaler)
+
+

+If a type—for example, +json.RawMessage—intends +to customize its JSON representation, it should implement +json.Marshaler, 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: +

+
+var _ json.Marshaler = (*MyMessage)(nil)
+
+

+As part of type-checking this static assignment of a +*RawMessage to a Marshaler, +the Go compiler will require that *RawMessage implements Marshaler. +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. +

A web server

diff --git a/doc/progs/unused1.go b/doc/progs/unused1.go new file mode 100644 index 0000000000..96a6d98a39 --- /dev/null +++ b/doc/progs/unused1.go @@ -0,0 +1,12 @@ +// skip + +package main + +import ( + "fmt" + "io" +) + +func main() { + greeting := "hello, world" +} diff --git a/doc/progs/unused2.go b/doc/progs/unused2.go new file mode 100644 index 0000000000..5c5f9d74f4 --- /dev/null +++ b/doc/progs/unused2.go @@ -0,0 +1,16 @@ +// compile + +package main + +import ( + "fmt" + "io" +) + +var _ = fmt.Printf +var _ io.Reader + +func main() { + greeting := "hello, world" + _ = greeting +} -- 2.48.1