| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // This package illustrates how basic try-catch exception handling |
| // can be emulated using goroutines, channels, and closures. |
| // |
| // This package is *not* intended as a general exception handler |
| // library. |
| // |
| package exception |
| |
| import ( |
| "fmt" |
| "runtime" |
| ) |
| |
| // A Handler function handles an arbitrary exception value x. |
| type Handler func(x interface{}) |
| |
| // An Exception carries an exception value. |
| type Exception struct { |
| Value interface{} // Value may be the nil exception |
| } |
| |
| // Try invokes a function f with a Handler to throw exceptions. |
| // The function f may terminate abnormally with an arbitrary |
| // exception x by calling throw(x) within f. If an exception is |
| // thrown, Try returns an *Exception; otherwise it returns nil. |
| // |
| // Usage pattern: |
| // |
| // if x := exception.Try(func(throw exception.Handler) { |
| // ... |
| // throw(42); // terminate f by throwing exception 42 |
| // ... |
| // }); x != nil { |
| // // catch exception, e.g. print it |
| // fmt.Println(x.Value); |
| // } |
| // |
| // Alternative: |
| // |
| // exception.Try(func(throw exception.Handler) { |
| // ... |
| // throw(42); // terminate f by throwing exception 42 |
| // ... |
| // }).Catch(func (x interface{}) { |
| // // catch exception, e.g. print it |
| // fmt.Println(x); |
| // }) |
| // |
| func Try(f func(throw Handler)) *Exception { |
| h := make(chan *Exception) |
| |
| // execute try block |
| go func() { |
| f(func(x interface{}) { |
| h <- &Exception{x} |
| runtime.Goexit() |
| }) |
| h <- nil // clean termination |
| }() |
| |
| return <-h |
| } |
| |
| |
| // If x != nil, Catch invokes f with the exception value x.Value. |
| // See Try for usage patterns. |
| func (x *Exception) Catch(f Handler) { |
| if x != nil { |
| f(x.Value) |
| } |
| } |
| |
| |
| func (x *Exception) String() string { |
| if x != nil { |
| return fmt.Sprintf("exception: %v", x.Value) |
| } |
| return "" |
| } |