@@ -803,3 +803,143 @@ func ExampleID() {
803803 }
804804 // Output: Error is a permission error
805805}
806+
807+ // ExampleWith demonstrates how to add context to errors without modifying the original error.
808+ // goerr.With(err, options...) adds context without modifying the original error
809+ func ExampleWith () {
810+ // Create an original error
811+ originalErr := goerr .New ("database connection failed" )
812+
813+ // Add context without modifying the original error
814+ // Original error remains unchanged, new error with additional context is returned
815+ enrichedErr := goerr .With (originalErr ,
816+ goerr .V ("user_id" , "user123" ),
817+ goerr .V ("component" , "auth-service" ),
818+ )
819+
820+ fmt .Println ("Original:" , originalErr .Error ())
821+ fmt .Println ("Enriched:" , enrichedErr .Error ())
822+
823+ // Verify original error has no additional context
824+ originalValues := goerr .Values (originalErr )
825+ fmt .Printf ("Original has %d values\n " , len (originalValues ))
826+
827+ // Verify enriched error has the context
828+ enrichedValues := goerr .Values (enrichedErr )
829+ fmt .Printf ("Enriched has %d values\n " , len (enrichedValues ))
830+ fmt .Printf ("User ID: %s\n " , enrichedValues ["user_id" ])
831+
832+ // Output:
833+ // Original: database connection failed
834+ // Enriched: database connection failed
835+ // Original has 0 values
836+ // Enriched has 2 values
837+ // User ID: user123
838+ }
839+
840+ // ExampleWrap demonstrates wrapping errors with additional context.
841+ // goerr.Wrap(cause, message, options...) wraps an existing error and adds additional information
842+ func ExampleWrap () {
843+ // Create a base error
844+ baseErr := fmt .Errorf ("connection timeout" )
845+
846+ // Wrap the error with additional context
847+ wrappedErr := goerr .Wrap (baseErr , "failed to connect to database" ,
848+ goerr .V ("host" , "localhost" ),
849+ goerr .V ("port" , 5432 ),
850+ goerr .V ("timeout" , "30s" ),
851+ )
852+
853+ fmt .Println ("Error:" , wrappedErr .Error ())
854+
855+ // Access the wrapped values
856+ values := goerr .Values (wrappedErr )
857+ fmt .Printf ("Host: %s\n " , values ["host" ])
858+ fmt .Printf ("Port: %v\n " , values ["port" ])
859+
860+ // Check if the original error is preserved
861+ if errors .Is (wrappedErr , baseErr ) {
862+ fmt .Println ("Original error is preserved" )
863+ }
864+
865+ // Output:
866+ // Error: failed to connect to database: connection timeout
867+ // Host: localhost
868+ // Port: 5432
869+ // Original error is preserved
870+ }
871+
872+ // ExampleBuilder demonstrates using Builder pattern for creating errors with shared context.
873+ // goerr.NewBuilder(options...) creates a builder, .With(options...) extends it, .New(msg) / .Wrap(err, msg) creates errors
874+ func ExampleBuilder () {
875+ // Create a builder with common context for a request
876+ builder := goerr .NewBuilder (
877+ goerr .V ("service" , "user-service" ),
878+ goerr .V ("request_id" , "req-12345" ),
879+ )
880+
881+ // Create errors using the builder - shared context is automatically included
882+ err1 := builder .New ("user not found" )
883+ err2 := builder .Wrap (fmt .Errorf ("connection refused" ), "database unavailable" )
884+
885+ // All errors created by the builder include the shared context
886+ fmt .Println ("Error 1:" , err1 .Error ())
887+ fmt .Printf ("Service: %s\n " , goerr .Values (err1 )["service" ])
888+
889+ fmt .Println ("Error 2:" , err2 .Error ())
890+ fmt .Printf ("Request ID: %s\n " , goerr .Values (err2 )["request_id" ])
891+
892+ // Extend the builder with additional context
893+ extendedBuilder := builder .With (goerr .V ("user_id" , "user789" ))
894+ err3 := extendedBuilder .New ("permission denied" )
895+
896+ fmt .Println ("Error 3:" , err3 .Error ())
897+ fmt .Printf ("User ID: %s\n " , goerr .Values (err3 )["user_id" ])
898+
899+ // Output:
900+ // Error 1: user not found
901+ // Service: user-service
902+ // Error 2: database unavailable: connection refused
903+ // Request ID: req-12345
904+ // Error 3: permission denied
905+ // User ID: user789
906+ }
907+
908+ // ExampleError_LogValue demonstrates structured logging with slog.LogValuer interface.
909+ // goerr.Error automatically implements slog.LogValuer for structured logging with slog.Any("error", err)
910+ func ExampleError_LogValue () {
911+ // Create an error with context
912+ err := goerr .New ("operation failed" ,
913+ goerr .V ("user_id" , "user123" ),
914+ goerr .V ("operation" , "delete_account" ),
915+ )
916+
917+ // The error implements slog.LogValuer interface automatically
918+ logValue := err .LogValue ()
919+
920+ // Extract some information from the log value for demonstration
921+ attrs := logValue .Group ()
922+ var message , operation string
923+ for _ , attr := range attrs {
924+ switch attr .Key {
925+ case "message" :
926+ message = attr .Value .String ()
927+ case "values" :
928+ valueGroup := attr .Value .Group ()
929+ for _ , valueAttr := range valueGroup {
930+ if valueAttr .Key == "operation" {
931+ operation = valueAttr .Value .String ()
932+ }
933+ }
934+ }
935+ }
936+
937+ fmt .Printf ("Message: %s\n " , message )
938+ fmt .Printf ("Operation: %s\n " , operation )
939+ fmt .Println ("Structured logging ready" )
940+
941+ // Output:
942+ // Message: operation failed
943+ // Operation: delete_account
944+ // Structured logging ready
945+ }
0 commit comments