A Golang boilerplate template, based on Vertical Slice Architecture and CQRS pattern with using Echo, Gorm, Zap, Viper, MediatR for CQRS and sarulabs/di for Dependency Injection.
MIT License
A Golang boilerplate template, based on Vertical Slice Architecture and CQRS pattern with using Echo, Gorm, Zap, Viper, MediatR for CQRS and sarulabs/di for Dependency Injection.
You can use this project as a template to build your Backend project in the Go language on top of this project.
Vertical Slice Architecture
as a high level architectureData Centric Architecture
based on CRUDCQRS Pattern
and Mediator Pattern
on top of mehdihadeli/Go-MediatR libraryDependency Injection
and Inversion of Control
on top of sarulabs/di libraryRESTFul api
with Echo framework and Open-Api
using swagger with swaggo/swag libraryGorm
and SQLLite
for databasesZap
for LoggingViper
for configuration managementlabstack/echo
- High performance, minimalist Go web frameworkuber-go/zap
- Blazing fast, structured, leveled logging in Go.emperror/errors
- Drop-in replacement for the standard library errors package and github.com/pkg/errorsstretchr/testify
- A toolkit with common assertions and mocks that plays nicely with the standard librarymehdihadeli/go-mediatr
- Mediator pattern implementation in Golang and helpful in creating CQRS based applications.swaggo/swag
- Automatically generate RESTful API documentation with Swagger 2.0 for Go.go-gorm/gorm
- The fantastic ORM library for Golang, aims to be developer friendlygo-playground/validator
- Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array divingsarulabs/di
- Dependency injection container in go (golang)spf13/viper
- Go configuration with fangscaarlos0/env
- A simple and zero-dependencies library to parse environment variables into structs.joho/godotenv
- A Go port of Ruby's dotenv library (Loads environment variables from .env files)mcuadros/go-defaults
- Go structures with default values using tagsprojects structure is based on:
We can run this Go boilerplate project with following steps:
cd your-workspace
.git clone https://github.com/mehdihadeli/go-vertical-slice-template
.cd go-vertical-slice-template
..env
similar to existing .env
file at the root directory for your environment variables.config/config.development.json
or config.production.json
files.go
if not installed on your machine.go run cmd/app/main.go
.# Run all tests
go test ./...
│ .env
│ .gitignore
│ go.mod
│ go.sum
│ golangci.yml
│ readme.md
├───cmd
│ └───app
│ main.go
│
├───config
│ config.development.json
│ config.go
│
├───docs
│ docs.go
│ swagger.json
│ swagger.yaml
│
└───internal
├───catalogs
│ ├───products
│ │ │ mapper.go
│ │ │
│ │ ├───contracts
│ │ │ │ endpoint.go
│ │ │ │ product_respository.go
│ │ │ │
│ │ │ └───params
│ │ │ product_route_params.go
│ │ │
│ │ ├───dtos
│ │ │ product_dto.go
│ │ │
│ │ ├───features
│ │ │ ├───creating_product
│ │ │ │ ├───commands
│ │ │ │ │ create_product.go
│ │ │ │ │ create_product_handler.go
│ │ │ │ │
│ │ │ │ ├───dtos
│ │ │ │ │ create_product_request_dto.go
│ │ │ │ │ create_product_response.go
│ │ │ │ │
│ │ │ │ ├───endpoints
│ │ │ │ │ create_product_endpoint.go
│ │ │ │ │
│ │ │ │ └───events
│ │ │ │ product_created.go
│ │ │ │ product_created_handler.go
│ │ │ │
│ │ │ └───getting_product_by_id
│ │ │ ├───dtos
│ │ │ │ get_product_by_id_request_dto.go
│ │ │ │ get_product_by_id_response.go
│ │ │ │
│ │ │ ├───endpoints
│ │ │ │ get_product_by_id_endpoint.go
│ │ │ │
│ │ │ └───queries
│ │ │ get_product_by_id.go
│ │ │ get_product_by_id_handler.go
│ │ │
│ │ ├───models
│ │ │ product.go
│ │ │
│ │ └───repository
│ │ inmemory_product_repository.go
│ │
│ └───shared
│ ├───app
│ │ ├───application
│ │ │ application.go
│ │ │ application_endpoints.go
│ │ │ application_mediatr.go
│ │ │ application_migration.go
│ │ │
│ │ └───application_builder
│ │ application_builder.go
│ │ application_builder_dependencies.go
│ │
│ └───behaviours
│ request_logger_behaviour.go
│
└───pkg
├───config
│ │ config_helper.go
│ │ dependency.go
│ │
│ └───environemnt
│ environment.go
│
├───constants
│ constants.go
│
├───database
│ │ db.go
│ │ dependency.go
│ │
│ └───options
│ gorm_options.go
│
└───reflection
└───type_mappper
type_mapper.go
type_mapper_test.go
unsafe_types.go
In this project I used vertical slice architecture or Restructuring to a Vertical Slice Architecture also I used feature folder structure in this project.
Minimize coupling
between slices
, and maximize coupling
in a slice
.Also here I used CQRS for decompose my features to very small parts that makes our application:
With using CQRS, our code will be more aligned with SOLID principles, especially with:
Here instead of some Technical Splitting for example a folder or layer for our services
, controllers
and data models
which increase dependencies between our technical splitting and also jump between layers or folders, We cut each business functionality into some vertical slices, and inner each of these slices we have Technical Folders Structure specific to that feature (command, handlers, infrastructure, repository, controllers, data models, ...).
Usually, when we work on a given functionality we need some technical things for example:
Now we could all of these things beside each other and it decrease jumping and dependencies between some layers or folders.
Keeping such a split works great with CQRS. It segregates our operations and slices the application code vertically instead of horizontally. In Our CQRS pattern each command/query handler is a separate slice. This is where you can reduce coupling between layers. Each handler can be a separated code unit, even copy/pasted. Thanks to that, we can tune down the specific method to not follow general conventions (e.g. use custom SQL query or even different storage). In a traditional layered architecture, when we change the core generic mechanism in one layer, it can impact all methods.
For live reloading in dev mode I use air library. for guid about using this tools you can read this article.
For running app in live reload mode
, inner type bellow command after installing air:
air