Skip to content

Commit 37ce5a8

Browse files
authored
docs: enhance documentation for Builder and error handling functions to improve clarity and usage examples (#32)
1 parent 4876abf commit 37ce5a8

File tree

7 files changed

+70
-8
lines changed

7 files changed

+70
-8
lines changed

builder.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ type Builder struct {
55
options []Option
66
}
77

8-
// NewBuilder creates a new Builder
8+
// NewBuilder creates a new Builder.
9+
// A Builder is useful for creating multiple errors that share a common context, such as a request ID or service name, without repeatedly specifying the same options.
910
func NewBuilder(options ...Option) *Builder {
1011
return &Builder{
1112
options: options,

builder_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package goerr_test
22

33
import (
4+
"fmt"
5+
"io"
46
"testing"
57

68
"github.com/m-mizutani/goerr/v2"
@@ -30,3 +32,23 @@ func TestBuilderWrap(t *testing.T) {
3032
t.Errorf("Unexpected cause: %v", err.Unwrap().Error())
3133
}
3234
}
35+
36+
func ExampleNewBuilder() {
37+
// Create a builder with common context for a request.
38+
builder := goerr.NewBuilder(
39+
goerr.Value("service", "auth-service"),
40+
goerr.Value("request_id", "req-9876"),
41+
)
42+
43+
// Use the builder to create errors.
44+
err1 := builder.New("user not found")
45+
err2 := builder.Wrap(io.EOF, "failed to read body")
46+
47+
// The context from the builder is automatically included.
48+
fmt.Println(goerr.Values(err1)["service"])
49+
fmt.Println(goerr.Values(err2)["request_id"])
50+
51+
// Output:
52+
// auth-service
53+
// req-9876
54+
}

error.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ func V(key string, value any) Option {
2525
}
2626

2727
// ID sets an error ID for Is() comparison.
28-
// Empty string ("") is treated as an invalid ID and will not be used for comparison.
29-
// When ID is set, errors.Is() will compare errors by ID instead of pointer equality.
28+
// When an ID is set, errors.Is() will compare errors by their ID string instead of by pointer equality. This allows for creating sentinel-like errors that can be matched even if they are wrapped.
29+
// An empty string ("") is treated as an invalid ID and will not be used for comparison.
3030
func ID(id string) Option {
3131
return func(err *Error) {
3232
err.id = id
@@ -443,9 +443,10 @@ func (x *Error) MarshalJSON() ([]byte, error) {
443443
return json.Marshal(x.Printable())
444444
}
445445

446-
// With adds contextual information to an error without modifying the original.
447-
// If err is goerr.Error, creates a new error preserving existing stacktrace and adds only new values/tags.
448-
// If err is not goerr.Error, wraps it with new stacktrace and adds values/tags.
446+
// With adds contextual information to an error without modifying the original. It is useful when you want to enrich an error with more context in a middleware or a higher-level function without altering the original error value.
447+
//
448+
// If err is a *goerr.Error, it creates a new *Error that preserves the original stacktrace and adds the new options.
449+
// If err is a standard error, it wraps the error in a new *goerr.Error with a new stacktrace and adds the options.
449450
func With(err error, options ...Option) *Error {
450451
if err == nil {
451452
return nil

error_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,3 +792,14 @@ func TestWith_KeyPrecedence(t *testing.T) {
792792
}
793793
})
794794
}
795+
796+
func ExampleID() {
797+
var ErrPermission = goerr.New("permission denied", goerr.ID("permission"))
798+
799+
err := goerr.Wrap(ErrPermission, "failed to open file")
800+
801+
if errors.Is(err, ErrPermission) {
802+
fmt.Println("Error is a permission error")
803+
}
804+
// Output: Error is a permission error
805+
}

tag.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (t tag) Format(s fmt.State, verb rune) {
4848

4949
// WithTags adds tags to the error. The tags are used to categorize errors.
5050
//
51-
// Deprecated: Use goerr.Tag instead.
51+
// Deprecated: Use the goerr.Tag option with goerr.New() or goerr.Wrap() instead.
5252
func (x *Error) WithTags(tags ...tag) *Error {
5353
for _, tag := range tags {
5454
x.tags[tag] = struct{}{}

typed_values.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ type TypedKey[T any] struct {
55
name string
66
}
77

8-
// NewTypedKey creates a new typed key with the given name
8+
// NewTypedKey creates a new type-safe key with the given name.
9+
// This key can then be used with TV() and GetTypedValue() to attach and retrieve strongly-typed values from an error, providing compile-time safety.
910
func NewTypedKey[T any](name string) TypedKey[T] {
1011
return TypedKey[T]{name: name}
1112
}

typed_values_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,3 +683,29 @@ func TestTypedValueClone(t *testing.T) {
683683
}
684684
})
685685
}
686+
687+
func ExampleNewTypedKey() {
688+
// Define typed keys at the package level for reuse.
689+
var UserIDKey = goerr.NewTypedKey[string]("user_id")
690+
var RequestIDKey = goerr.NewTypedKey[int]("request_id")
691+
692+
// Attach typed values when creating an error.
693+
err := goerr.New("request failed",
694+
goerr.TV(UserIDKey, "blue"),
695+
goerr.TV(RequestIDKey, 12345),
696+
)
697+
698+
// Retrieve the typed value later.
699+
if userID, ok := goerr.GetTypedValue(err, UserIDKey); ok {
700+
// The retrieved value has the correct type (string), no assertion needed.
701+
fmt.Printf("User ID: %s\n", userID)
702+
}
703+
704+
if reqID, ok := goerr.GetTypedValue(err, RequestIDKey); ok {
705+
fmt.Printf("Request ID: %d\n", reqID)
706+
}
707+
708+
// Output:
709+
// User ID: blue
710+
// Request ID: 12345
711+
}

0 commit comments

Comments
 (0)