Documentation
¶
Overview ¶
Package try emulates aspects of the ill-fated "try" proposal using generics. See https://golang.org/issue/32437 for inspiration.
Example usage:
func Fizz(...) (..., err error) {
defer try.Handle(&err, func() {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
})
... := try.E2(Buzz(...))
return ..., nil
}
This package is a sharp tool and should be used with care. Quick and easy error handling can occlude critical error handling logic. Panic handling generally should not cross package boundaries or be an explicit part of an API.
Package try is a good fit for short Go programs and unit tests where development speed is a greater priority than reliability. Since the E functions panic if an error is encountered, recovering in such programs is optional.
Code before try:
func (a *MixedArray) UnmarshalNext(uo json.UnmarshalOptions, d *json.Decoder) error {
switch t, err := d.ReadToken(); {
case err != nil:
return err
case t.Kind() != '[':
return fmt.Errorf("got %v, expecting array start", t.Kind())
}
if err := uo.UnmarshalNext(d, &a.Scalar); err != nil {
return err
}
if err := uo.UnmarshalNext(d, &a.Slice); err != nil {
return err
}
if err := uo.UnmarshalNext(d, &a.Map); err != nil {
return err
}
switch t, err := d.ReadToken(); {
case err != nil:
return err
case t.Kind() != ']':
return fmt.Errorf("got %v, expecting array end", t.Kind())
}
return nil
}
Code after try:
func (a *MixedArray) UnmarshalNext(uo json.UnmarshalOptions, d *json.Decoder) (err error) {
defer try.Handle(&err)
if t := try.E1(d.ReadToken()); t.Kind() != '[' {
return fmt.Errorf("found %v, expecting array start", t.Kind())
}
try.E(uo.UnmarshalNext(d, &a.Scalar))
try.E(uo.UnmarshalNext(d, &a.Slice))
try.E(uo.UnmarshalNext(d, &a.Map))
if t := try.E1(d.ReadToken()); t.Kind() != ']' {
return fmt.Errorf("found %v, expecting array end", t.Kind())
}
return nil
}
Quick tour of the API ¶
The E family of functions all remove a final error return, panicking if non-nil.
Or and Or2 are non-panicking alternatives: they capture a call's results, and Else returns them if the error is nil; otherwise Else logs the error with slog.Error and returns the given fallback values instead.
port := try.Or(strconv.Atoi(s)).Else(8080)
Handle recovers from that panic and allows assignment of the error to a return error value. Each recovered error is also logged with slog.Error. Other panics are not recovered.
func f() (err error) {
defer try.Handle(&err)
...
}
Handle also accepts optional functions that are called after the error is assigned, which may inspect or modify the error.
func f() (err error) {
defer try.Handle(&err, func() {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
})
...
}
func foo(i int) (err error) {
defer try.Handle(&err, func() {
err = fmt.Errorf("unable to foo %d: %w", i, err)
})
...
}
F wraps an error with file and line information and calls a function on error. It inter-operates well with testing.TB and log.Fatal.
func TestFoo(t *testing.T) {
defer try.F(t.Fatal)
...
}
func main() {
defer try.F(log.Fatal)
...
}
Recover is like F, but it supports more complicated error handling by passing the error and runtime frame directly to a function.
func f() {
defer try.Recover(func(err error, frame runtime.Frame) {
// do something useful with err and frame
})
...
}
The recover functions (Handle, F, and Recover) only recover panic values raised by the E functions. As a special case, they also recover any panic value that implements
interface{ TryRecover() error }
where TryRecover reports a non-nil error. If only the pointer type of the panic value implements TryRecover, a pointer to a copy of the value is used, so such values may be panicked by value or by pointer. This permits packages that use their own panic-based error signaling to interoperate with this package without depending on it. Such panic values carry no frame information: Recover reports a zero runtime.Frame for them.
Index ¶
- func E(err error)
- func E1[A any](a A, err error) A
- func E2[A, B any](a A, b B, err error) (A, B)
- func E3[A, B, C any](a A, b B, c C, err error) (A, B, C)
- func E4[A, B, C, D any](a A, b B, c C, d D, err error) (A, B, C, D)
- func F(fn func(...any))
- func Handle(errptr *error, fns ...func())
- func Or[A any](a A, err error) or1[A]
- func Or2[A, B any](a A, b B, err error) or2[A, B]
- func Recover(fn func(err error, frame runtime.Frame))
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func F ¶
func F(fn func(...any))
F recovers an error previously panicked with an E function, wraps it, and passes it to fn. The wrapping includes the file and line of the runtime frame in which it occurred. F pairs well with testing.TB.Fatal and log.Fatal.
func Handle ¶
func Handle(errptr *error, fns ...func())
Handle recovers an error previously panicked with an E function and stores it into errptr. If it recovers an error, it logs it with slog.Error as "try: recovered: <error>", where the log record includes a "src" attribute of the form "<package>/<file>:<line>" if the frame in which the error occurred is known, and then calls each fn in order, which may inspect or modify the error through errptr.
func Or ¶
Or captures the result of a call with one non-error value for use with Else:
port := try.Or(strconv.Atoi(s)).Else(8080)
Types ¶
This section is empty.
Directories
¶
| Path | Synopsis |
|---|---|
|
This program demonstrates recovering panic values from a foreign package that implements TryRecover, alongside ordinary use of the E functions.
|
This program demonstrates recovering panic values from a foreign package that implements TryRecover, alongside ordinary use of the E functions. |
|
extlib
Package extlib simulates a third-party library that uses its own panic-based error signaling.
|
Package extlib simulates a third-party library that uses its own panic-based error signaling. |
|
or
command
This program demonstrates the non-panicking Or functions, which return a fallback value when the call fails.
|
This program demonstrates the non-panicking Or functions, which return a fallback value when the call fails. |
|
panic
command
|
|
|
simple
command
|
|
|
simple2
command
|