From: Rob Pike
+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,75 +1372,124 @@ By the way, the idea of using Write on a slice of bytes
is implemented by bytes.Buffer.
os.Error should
-describe the error and provide context.
-For example, os.Open returns an os.PathError:
+
+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;
- Path string;
- Error Error;
+ 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();
+ return e.Op + " " + e.Path + ": " + e.Error.String();
}
-
-PathError's String formats
-the error nicely, including the operation and file name
-tha failed; just printing the error generates a
-message, such as
+PathError's String generates
+a string like this:
open /etc/passwx: no such file or directory
-that is useful even if printed far from the call that -triggered it. +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 guard to look for specific
+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
-to see if it is os.EPERM or os.ENOENT,
-for instance.
+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
+}
+
+
+