pull try out of Add
				
					
				
			deferring a recovery handler is normal in Go but opaque. Pulling out a helper for this (`try`) makes it more obvious that this is just another "if this operation fails, return error" case.
This commit is contained in:
		| @@ -220,7 +220,7 @@ var ErrFieldSetPanic = fmt.Errorf("%w: panic when setting", ErrBadFieldLabel) | ||||
| // Use a FieldLabel to add an amount to the matching field. If no such | ||||
| // field can be found, the field is not exported, or the field is not | ||||
| // of type float64, this returns an error ad does not change any values. | ||||
| func (k *KoboldMine) Add(which FieldLabel, amount float64) (finalErr error) { | ||||
| func (k *KoboldMine) Add(which FieldLabel, amount float64) error { | ||||
| 	kv := reflect.ValueOf(k).Elem() | ||||
| 	f := kv.FieldByName(string(which)) | ||||
| 	if !f.IsValid() { | ||||
| @@ -230,15 +230,8 @@ func (k *KoboldMine) Add(which FieldLabel, amount float64) (finalErr error) { | ||||
| 		return fmt.Errorf("cannot add %f to field %q: %w", amount, which, ErrFieldNotFloat) | ||||
| 	} | ||||
|  | ||||
| 	defer func() { | ||||
| 		if r := recover(); r != nil { | ||||
| 			if e, ok := r.(error); ok { | ||||
| 				finalErr = fmt.Errorf("could not add %f to field %q: %w: %w", amount, which, ErrFieldSetPanic, e) | ||||
| 			} else { | ||||
| 				finalErr = fmt.Errorf("could not add %f to field %q: %w: %v", amount, which, ErrFieldSetPanic, r) | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	f.SetFloat(f.Float() + amount) | ||||
| 	if err := try(func() { f.SetFloat(f.Float() + amount) }); err != nil { | ||||
| 		return fmt.Errorf("could not add %f to field %q: %w", amount, which, err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| package koboldsim | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
|  | ||||
| 	"golang.org/x/exp/constraints" | ||||
| @@ -47,3 +49,23 @@ func clamp[T constraints.Ordered](a, b, c T) T { | ||||
| 	// `a` is neither most nor least; therefore, `a` is mid | ||||
| 	return a | ||||
| } | ||||
|  | ||||
| var ErrWrappedPanic = errors.New("panic") | ||||
|  | ||||
| // try catches a panic in the provided func and demotes it to an error, if any | ||||
| // panic occurs. The returned error, if any, wraps `ErrWrappedPanic`. If the | ||||
| // panic argument is itself an error, it is also wrapped; otherwise, it is | ||||
| // stringified into the error message using `%v`. | ||||
| func try(f func()) (finalErr error) { | ||||
| 	defer func() { | ||||
| 		if r := recover(); r != nil { | ||||
| 			if e, ok := r.(error); ok { | ||||
| 				finalErr = fmt.Errorf("%w: %w", ErrWrappedPanic, e) | ||||
| 				return | ||||
| 			} | ||||
| 			finalErr = fmt.Errorf("%w: %v", ErrWrappedPanic, r) | ||||
| 		} | ||||
| 	}() | ||||
| 	f() | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user