forked from goplus/tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
81 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// In Go+ it's idiomatic to communicate errors via an | ||
// explicit, separate return value. This contrasts with | ||
// the exceptions used in languages like Java and Ruby and | ||
// the overloaded single result / error value sometimes | ||
// used in C. Go+'s approach makes it easy to see which | ||
// functions return errors and to handle them using the | ||
// same language constructs employed for any other, | ||
// non-error tasks. | ||
|
||
import ( | ||
"errors" | ||
) | ||
|
||
// By convention, errors are the last return value and | ||
// have type `error`, a built-in interface. | ||
func f1(arg int) (int, error) { | ||
if arg == 42 { | ||
|
||
// `errors.New` constructs a basic `error` value | ||
// with the given error message. | ||
return -1, errors.new("can't work with 42") | ||
|
||
} | ||
|
||
// A `nil` value in the error position indicates that | ||
// there was no error. | ||
return arg + 3, nil | ||
} | ||
|
||
// It's possible to use custom types as `error`s by | ||
// implementing the `Error()` method on them. Here's a | ||
// variant on the example above that uses a custom type | ||
// to explicitly represent an argument error. | ||
type argError struct { | ||
arg int | ||
prob string | ||
} | ||
|
||
func (e *argError) Error() string { | ||
return sprintf("%d - %s", e.arg, e.prob) | ||
} | ||
|
||
func f2(arg int) (int, error) { | ||
if arg == 42 { | ||
|
||
// In this case we use `&argError` syntax to build | ||
// a new struct, supplying values for the two | ||
// fields `arg` and `prob`. | ||
return -1, &argError{arg, "can't work with it"} | ||
} | ||
return arg + 3, nil | ||
} | ||
|
||
// The two loops below test out each of our | ||
// error-returning functions. Note that the use of an | ||
// inline error check on the `if` line is a common | ||
// idiom in Go code. | ||
for _, i := range []int{7, 42} { | ||
if r, e := f1(i); e != nil { | ||
println "f1 failed:", e | ||
} else { | ||
println "f1 worked:", r | ||
} | ||
} | ||
for _, i := range []int{7, 42} { | ||
if r, e := f2(i); e != nil { | ||
println "f2 failed:", e | ||
} else { | ||
println "f2 worked:", r | ||
} | ||
} | ||
|
||
// If you want to programmatically use the data in | ||
// a custom error, you'll need to get the error as an | ||
// instance of the custom error type via type | ||
// assertion. | ||
_, e := f2(42) | ||
if ae, ok := e.(*argError); ok { | ||
println ae.arg | ||
println ae.prob | ||
} |