From 97a695752040ccf96335c5e593bd9856a61a5fb6 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Tue, 14 Oct 2025 18:04:39 -0500 Subject: thoughts on errors --- errors.go | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) (limited to 'errors.go') diff --git a/errors.go b/errors.go index 807386d..7f318af 100644 --- a/errors.go +++ b/errors.go @@ -1,5 +1,113 @@ package config -import "errors" +import ( + "errors" + "fmt" +) var NotInitialized error = errors.New("your application config not initialized") + +// Finally, declare a package-level variable of your new type. +// This is the "sentinel" error that users will compare against. +var ErrNotInitialized = NotInitializedError{} + +func ErrdKeyFalse(varname string) error { + return errors.New("config key '" + varname + "' was not 'true'") +} + +func ErrdKeyNotSet(varname string) error { + return errors.New("config key '" + varname + "' was not set") +} + +// thanks gemini for this example custom error example + +// --- 1. A Custom Error Type for "Not Initialized" --- + +// First, define a new, named type for your error. A struct is common. +type NotInitializedError struct{} + +// Now, attach the Error() method to your new type. This makes it +// satisfy the built-in 'error' interface. +func (e NotInitializedError) Error() string { + return "your application config not initialized" +} + +// (Your Goal) Attach a custom String() method for pretty printing. +// This will be used by fmt.Println, for example. +func (e NotInitializedError) String() string { + return "func main() didn't initialize this" +} + +// --- 2. A Custom Error Type with an Is() Method --- + +// Let's make a more complex error for key-not-set issues. +type KeyNotSetError struct { + KeyName string // It can hold data! +} + +// Make it satisfy the 'error' interface. +func (e KeyNotSetError) Error() string { + return fmt.Sprintf("config key '%s' was not set", e.KeyName) +} + +// (Your Goal) Define a custom Is() method. +// errors.Is(someError, ErrKeyNotSet) will call this method. +func (e KeyNotSetError) Is(target error) bool { + // We can check if the target is of the same type. + // This allows errors.Is(err, KeyNotSetError{}) to work, + // checking for the general *type* of error. + _, ok := target.(KeyNotSetError) + return ok +} + +// A helper function to create this error. +func NewKeyNotSetError(varname string) error { + return KeyNotSetError{KeyName: varname} +} + +// A generic sentinel error for this category. +var ErrKeyNotSet = KeyNotSetError{} + +/* +// --- Example Usage --- + +func checkConfig() error { + // Pretend the config is not initialized. + return ErrNotInitialized +} + +func checkKey(key string) error { + // Pretend a specific key is not set. + return NewKeyNotSetError(key) +} + +func main() { + // --- Test Case 1: The NotInitializedError --- + err1 := checkConfig() + + // errors.Is() works perfectly because it compares the variable directly. + if errors.Is(err1, ErrNotInitialized) { + fmt.Println("Check 1: errors.Is correctly identified ErrNotInitialized.") + } + + // fmt.Println will use your custom String() method! + fmt.Println("Check 2: Printing the error uses the custom String() method:") + fmt.Println(err1) + fmt.Println() + + // --- Test Case 2: The KeyNotSetError --- + err2 := checkKey("database_url") + + // This works because of your custom Is() method! + // We are checking if err2 is of the *type* KeyNotSetError. + if errors.Is(err2, ErrKeyNotSet) { + fmt.Println("Check 3: errors.Is correctly identified the general KeyNotSetError type.") + } + + // You can also get the underlying error to inspect its data. + var keyErr KeyNotSetError + if errors.As(err2, &keyErr) { + fmt.Printf("Check 4: errors.As extracted the error data. Key not set: %s\n", keyErr.KeyName) + } +} +*/ -- cgit v1.2.3