
kratos-errors
Advanced Kratos error handling package with type-safe operations and nil interface trap prevention.
CHINESE README
δΈζθ―΄ζ
Main Features
π― Type-Safe Error Handling: Simplified API to manipulate Kratos errors without naming conflicts
ποΈ Typed Error Creation: Build and match errors straight from generated reason enums (kratoserrors)
β‘ Safe Error Handling: Solves Go's notorious (*T)(nil) != nil trap through intelligent adaptation
π Testing Integration: Complete testify/assert and testify/require helpers to test Kratos errors
Installation
go get github.com/yylego/kratos-errors
Usage
Basic Error Handling
import "github.com/yylego/kratos-errors/errorskratos"
// Type-safe error conversion
err := someFunction()
if erk, ok := errorskratos.As(err); ok {
fmt.Printf("Kratos error: %s (code: %d)\n", erk.Reason, erk.Code)
}
// Error comparison
erk1 := errors.BadRequest("INVALID_INPUT", "missing field")
erk2 := errors.BadRequest("INVALID_INPUT", "wrong format")
if errorskratos.Is(erk1, erk2) {
// Same error type (reason and code match)
}
// Convert generic error to Kratos error
erk := errorskratos.From(err)
Concise Error Creation (kratoserrors)
import "github.com/yylego/kratos-errors/kratoserrors"
// Create type-safe error with enum
erk := kratoserrors.NewError(404, ErrorReason_USER_NOT_FOUND, "user %d not found", userID)
// Check error type
if kratoserrors.IsError(err, ErrorReason_USER_NOT_FOUND, 404) {
// Handle user not found error
}
Testing with Assert
import "github.com/yylego/kratos-errors/errorskratos/must/erkassert"
func TestSomething(t *testing.T) {
var erk *errors.Error
// Assert no error (handles nil interface with safe checks)
erkassert.NoError(t, erk)
// Assert error exists
erk = errors.InternalServer("SERVER_ERROR", "database failed")
erkassert.Error(t, erk)
// Assert error equivalence
expected := errors.BadRequest("INVALID_INPUT", "test")
erkassert.Is(t, expected, erk)
}
Testing with Require
import "github.com/yylego/kratos-errors/errorskratos/must/erkrequire"
func TestCritical(t *testing.T) {
var erk *errors.Error
// Require no error (stops test at once if error exists)
erkrequire.NoError(t, erk)
// Continue when no error...
}
Production Error Enforcement
import "github.com/yylego/kratos-errors/errorskratos/must/erkmust"
func criticalOperation() {
erk := doSomethingImportant()
// Panic if error exists (with structured logging)
erkmust.Done(erk)
// Use Must (same function, different name)
erkmust.Must(erk)
}
Package Structure
kratos-errors/
βββ errorskratos/ # Error inspection (As, Is, From)
β βββ errors.go
β βββ erkadapt/ # Nil interface adaptation
β βββ must/ # Testing and enforcement tools
β βββ erkassert/ # testify/assert helpers
β βββ erkrequire/ # testify/require helpers
β βββ erkmust/ # Production panic utilities
βββ kratoserrors/ # Typed error creation and check (NewError, IsError)
βββ Makefile # CI: test/coverage/bench
βββ internal/ # PB generation via buf
βββ buf.yaml
βββ buf.gen.yaml
βββ Makefile # generate PB via buf
βββ errorspb/ # proto + generated pb.go
βββ proto3ps/ # vendored proto imports (errors + google)
Core Capabilities
The Nil Interface Issue
Go has a known issue where a typed nil value doesn't match nil when converted to interface:
var erk *errors.Error = nil
var err error = erk
fmt.Println(erk == nil) // true
fmt.Println(err == nil) // false (!!)
This causes issues in error handling. kratos-errors solves this through intelligent adaptation in each function.
Clean Naming
The Erk type alias avoids import conflicts between standard errors package and Kratos errors:
// Instead of this confusion:
import (
stderrors "errors"
"github.com/go-kratos/kratos/v3/errors"
)
// Just use:
import "github.com/yylego/kratos-errors/errorskratos"
// And work with errorskratos.Erk
More Projects
- kratos-ebz - Error type that doesn't implement error interface
π License
MIT License. See LICENSE.
π€ Contributing
Contributions are welcome! Report bugs, suggest features, and contribute code:
- π Found a mistake? Open an issue on GitHub with reproduction steps
- π‘ Have a feature idea? Create an issue to discuss the suggestion
- π Documentation confusing? Report it so we can improve
- π Need new features? Share the use cases to help us understand requirements
- β‘ Performance issue? Help us optimize through reporting slow operations
- π§ Configuration problem? Ask questions about complex setups
- π’ Follow project progress? Watch the repo to get new releases and features
- π Success stories? Share how this package improved the workflow
- π¬ Feedback? We welcome suggestions and comments
π§ Development
New code contributions, follow this process:
- Fork: Fork the repo on GitHub (using the webpage UI).
- Clone: Clone the forked project (
git clone https://github.com/yourname/repo-name.git).
- Navigate: Navigate to the cloned project (
cd repo-name)
- Branch: Create a feature branch (
git checkout -b feature/xxx).
- Code: Implement the changes with comprehensive tests
- Testing: (Golang project) Ensure tests pass (
go test ./...) and follow Go code style conventions
- Documentation: Update documentation to support client-facing changes and use significant commit messages
- Stage: Stage changes (
git add .)
- Commit: Commit changes (
git commit -m "Add feature xxx") ensuring backward compatible code
- Push: Push to the branch (
git push origin feature/xxx).
- PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.
Please ensure tests pass and include relevant documentation updates.
π Support
Welcome to contribute to this project via submitting merge requests and reporting issues.
Project Support:
- β Give GitHub stars if this project helps you
- π€ Share with teammates and (golang) programming friends
- π Write tech blogs about development tools and workflows - we provide content writing support
- π Join the ecosystem - committed to supporting open source and the (golang) development scene
Have Fun Coding with this package! πππ
GitHub Stars
