// 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 ""; }