Skip to main content

Examples

Minimal example

package main

import (
"fmt"

"github.com/ygrebnov/errorc"
)

func main() {
err := errorc.With(
errorc.New("query failed"),
errorc.String("query", "select * from users"),
errorc.Int("retries", 3),
)

fmt.Println(err)
}

Output:

query failed, query: select * from users, retries: 3

Sentinel errors with errors.Is

package main

import (
"errors"
"fmt"

"github.com/ygrebnov/errorc"
)

func main() {
ErrInvalidInput := errorc.New("invalid input")

err := errorc.With(
ErrInvalidInput,
errorc.String("field", "email"),
errorc.String("reason", "required"),
)

fmt.Println(err)
fmt.Println(errors.Is(err, ErrInvalidInput))
}

Output:

invalid input, field: email, reason: required
true

Typed errors with errors.As

package main

import (
"errors"
"fmt"

"github.com/ygrebnov/errorc"
)

type ValidationError struct {
Message string
}

func (e *ValidationError) Error() string {
return e.Message
}

func main() {
err := errorc.With(
&ValidationError{Message: "invalid input"},
errorc.String("field", "email"),
)

var ve *ValidationError
fmt.Println(errors.As(err, &ve))
fmt.Println(ve.Message)
}

Output:

true
invalid input

Use Error to capture an underlying cause

package main

import (
"errors"
"fmt"

"github.com/ygrebnov/errorc"
)

func main() {
cause := errors.New("disk full")
err := errorc.With(errorc.New("operation failed"), errorc.Error("cause", cause))

fmt.Println(err)
}

Output:

operation failed, cause: disk full

Structured keys with the keys library

errorc works well with keys when you want hierarchical field names.

package main

import (
"fmt"

"github.com/ygrebnov/errorc"
"github.com/ygrebnov/keys"
)

func main() {
userKey := keys.Factory(keys.WithSegments("user"))
requestKey := keys.Factory(keys.WithSegments("request"))

err := errorc.With(
errorc.New("invalid input"),
errorc.String(userKey("id"), "123"),
errorc.String(requestKey("trace_id"), "abc-xyz"),
)

fmt.Println(err)
}

Output:

invalid input, user.id: 123, request.trace_id: abc-xyz

See the keys examples for more ways to build reusable structured key namespaces.


Namespaced errors

Use namespaces when you want identifiers like storage: read_failed.

package main

import (
"fmt"

"github.com/ygrebnov/errorc"
)

func main() {
storageErr := errorc.ErrorFactory("storage")
fmt.Println(storageErr("read_failed"))
}

Output:

storage: read_failed

Running package examples

The package includes Example* functions that can be executed with go test.

# run unit tests and examples
go test ./...

# run only examples
go test -run Example ./...

You can also browse the upstream examples on pkg.go.dev or in the module source files such as example_test.go.