https://github.com/swaggest/usecase
Clean Architecture Use Case for Go
https://github.com/swaggest/usecase
clean-architecture hacktoberfest usecase
Last synced: 10 months ago
JSON representation
Clean Architecture Use Case for Go
- Host: GitHub
- URL: https://github.com/swaggest/usecase
- Owner: swaggest
- License: mit
- Created: 2020-01-02T20:41:07.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-12-19T01:13:44.000Z (over 2 years ago)
- Last Synced: 2025-04-22T12:55:53.245Z (about 1 year ago)
- Topics: clean-architecture, hacktoberfest, usecase
- Language: Go
- Homepage: https://pkg.go.dev/github.com/swaggest/usecase
- Size: 47.9 KB
- Stars: 34
- Watchers: 1
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Use Case Interactor
[](https://github.com/swaggest/usecase/actions?query=branch%3Amaster+workflow%3Atest-unit)
[](https://codecov.io/gh/swaggest/usecase)
[](https://pkg.go.dev/github.com/swaggest/usecase)


This module defines generalized contract of *Use Case Interactor* to enable
[The Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
in Go application.

## Why?
Isolating transport layer from business logic reduces coupling and allows better control on both transport and business
sides. For example the application needs to consume AMQP events and act on them, with isolated use case interactor it is
easy to trigger same action with HTTP message (as a part of developer tools).
Use case interactors declare their ports and may serve as a source of information for documentation automation.
This abstraction is intended for use with automated transport layer, for example see [`REST`](https://github.com/swaggest/rest).
## Usage
### Input/Output Definitions
```go
// Configure use case interactor in application layer.
type myInput struct {
Param1 int `path:"param1" description:"Parameter in resource path." multipleOf:"2"`
Param2 string `json:"param2" description:"Parameter in resource body."`
}
type myOutput struct {
Value1 int `json:"value1"`
Value2 string `json:"value2"`
}
```
### Classic API
```go
u := usecase.NewIOI(new(myInput), new(myOutput), func(ctx context.Context, input, output interface{}) error {
var (
in = input.(*myInput)
out = output.(*myOutput)
)
if in.Param1%2 != 0 {
return status.InvalidArgument
}
// Do something to set output based on input.
out.Value1 = in.Param1 + in.Param1
out.Value2 = in.Param2 + in.Param2
return nil
})
```
### Generic API with type parameters
With `go1.18` and later (or [`gotip`](https://pkg.go.dev/golang.org/dl/gotip)) you can use simplified generic API instead
of classic API based on `interface{}`.
```go
u := usecase.NewInteractor(func(ctx context.Context, input myInput, output *myOutput) error {
if in.Param1%2 != 0 {
return status.InvalidArgument
}
// Do something to set output based on input.
out.Value1 = in.Param1 + in.Param1
out.Value2 = in.Param2 + in.Param2
return nil
})
```
### Further Configuration And Usage
```go
// Additional properties can be configured for purposes of automated documentation.
u.SetTitle("Doubler")
u.SetDescription("Doubler doubles parameter values.")
u.SetTags("transformation")
u.SetExpectedErrors(status.InvalidArgument)
u.SetIsDeprecated(true)
```
Then use configured use case interactor with transport/documentation/etc adapter.
For example with [REST](https://github.com/swaggest/rest/blob/v0.1.18/_examples/basic/main.go#L95-L96) router:
```go
// Add use case handler to router.
r.Method(http.MethodPost, "/double/{param1}", nethttp.NewHandler(u))
```