From d2228692b279827a61100bbf8350688fe230448a Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Mon, 12 Oct 2009 21:18:23 -0700 Subject: [PATCH] type switches errors R=rsc DELTA=150 (74 added, 34 deleted, 42 changed) OCL=35647 CL=35650 --- doc/effective_go.html | 226 +++++++++++++++++++++++++----------------- 1 file changed, 133 insertions(+), 93 deletions(-) diff --git a/doc/effective_go.html b/doc/effective_go.html index ec40ce87abf..73b91ca80f5 100644 --- a/doc/effective_go.html +++ b/doc/effective_go.html @@ -628,6 +628,28 @@ func Compare(a, b []byte) int { } +

+A switch can also be used to discover the dynamic type of an interface +variable. Such a type switch uses the syntax of a type +assertion with the keyword type inside the parentheses. +If the switch declares a variable in the expression, the variable will +have the corresponding type in each clause. +

+
+switch t := interfaceValue.(type) {
+default:
+	fmt.Printf("unexpected type");
+case bool:
+	fmt.Printf("boolean %t\n", t);
+case int:
+	fmt.Printf("integer %d\n", t);
+case *bool:
+	fmt.Printf("pointer to boolean %t\n", *t);
+case *int:
+	fmt.Printf("pointer to integer %d\n", *t);
+}
+
+

Functions

Multiple return values

@@ -1350,101 +1372,9 @@ By the way, the idea of using Write on a slice of bytes is implemented by bytes.Buffer.

-

More to come

+

Interfaces

+ +

Errors

+ +

+Library routines must often return some sort of error indication to +the caller. As mentioned earlier, Go's multivalue return makes it +easy to return a detailed error description alongside the normal +return value. By convention, errors have type os.Error, +a simple interface. +

+
+type Error interface {
+    String() string;
+}
+
+

+A library writer is free to implement this interface with a +richer model under the covers, making it possible not only +to see the error but also to provide some context. +For example, os.Open returns an os.PathError. +

+
+// PathError records an error and the operation and
+// file path that caused it.
+type PathError struct {
+	Op string;    // "open", "unlink", etc.
+	Path string;  // The associated file.
+	Error Error;  // Returned by the system call.
+}
+
+func (e *PathError) String() string {
+	return e.Op + " " + e.Path + ": " + e.Error.String();
+}
+
+

+PathError's String generates +a string like this: +

+
+open /etc/passwx: no such file or directory
+
+

+Such an error, which includes the problematic file name, the +operation, and the operating system error it triggered, is useful even +if printed far from the call that caused it; +it is much more informative than the plain +"no such file or directory". +

+ +

+Callers that care about the precise error details can +use a type switch or a type assertion to look for specific +errors and extract details. For PathErrors +this might include examining the internal Error +field for recoverable failures. +

+ +
+for try := 0; try < 2; try++ {
+	file, err := os.Open(filename, os.O_RDONLY, 0);
+	if err == nil {
+		return
+	}
+	if e, ok := err.(*os.PathError); ok && e.Error == os.ENOSPC {
+		deleteTempFiles();  // Recover some space.
+		continue
+	}
+	return
+}
+
+ +

Testing

+ +

More to come

+ +