A Go (Golang) Backend Clean Architecture project with Gin, MongoDB, JWT Authentication Middleware, Test, and Docker.
You can use this project as a template to build your Backend project in the Go language on top of this project.
Before creating this project, I have gone through more than 20 projects related to the Go(Golang) Clean Architecture on GitHub.
Thanks to all those projects, I learned a lot from all of those. As I keep saying:
The best way to learn to code is to code. But, to write good code, you will also have to read good code. Make a habit of reading good code. You can find many open-source projects on GitHub and start reading.
Then for the implementation part, I combined all of my ideas, experiences, and learnings from those projects to create this project.
And as always I would love to get feedback on my project. This helps everyone and most importantly me.
Learn about this project architecture in detail from the blogs mentioned below:
- Go Backend Clean Architecture
- Go JWT Authentication Middleware
- Configuration with Viper in Go
- Test with Testify and Mockery in Go
- Router
- Controller
- Usecase
- Repository
- Domain
Hi, I am Amit Shekhar, I have mentored many developers, and their efforts landed them high-paying tech jobs, helped many tech companies in solving their unique problems, and created many open-source libraries being used by top companies. I am passionate about sharing knowledge through open-source, blogs, and videos.
You can connect with me on:
- What is System Design?
- Twitter Timeline Design with Fanout Approach - System Design
- HTTP Request vs HTTP Long-Polling vs WebSocket vs Server-Sent Events
- YouTube Video Upload Service - System Design
- What is Consistent Hashing?
- Capacity Estimation: Back-of-the-envelope calculation - Twitter
- gin: Gin is an HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need a smashing performance, get yourself some Gin.
- mongo go driver: The Official Golang driver for MongoDB.
- jwt: JSON Web Tokens are an open, industry-standard RFC 7519 method for representing claims securely between two parties. Used for Access Token and Refresh Token.
- viper: For loading configuration from the
.env
file. Go configuration with fangs. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, INI, envfile, or Java properties formats. - bcrypt: Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing algorithm.
- testify: A toolkit with common assertions and mocks that plays nicely with the standard library.
- mockery: A mock code autogenerator for Golang used in testing.
- Check more packages in
go.mod
.
JWT Authentication Middleware for Access Token Validation.
We can run this Go Backend Clean Architecture project with or without Docker. Here, I am providing both ways to run this project.
- Clone this project
# Move to your workspace
cd your-workspace
# Clone this project into your workspace
git clone https://github.com/amitshekhariitbhu/go-backend-clean-architecture.git
# Move to the project root directory
cd go-backend-clean-architecture
- Create a file
.env
similar to.env.example
at the root directory with your configuration. - Install
go
if not installed on your machine. - Install
MongoDB
if not installed on your machine. - Important: Change the
DB_HOST
tolocalhost
(DB_HOST=localhost
) in.env
configuration file.DB_HOST=mongodb
is needed only when you run with Docker. - Run
go run cmd/main.go
. - Access API using
http://localhost:8080
- Create a file
.env
similar to.env.example
at the root directory with your configuration. - Install Docker and Docker Compose.
- Run
docker-compose up -d
. - Access API using
http://localhost:8080
# Run all tests
go test ./...
In this project, to test, we need to generate mock code for the use-case, repository, and database.
# Generate mock code for the usecase and repository
mockery --dir=domain --output=domain/mocks --outpkg=mocks --all
# Generate mock code for the database
mockery --dir=mongo --output=mongo/mocks --outpkg=mocks --all
Whenever you make changes in the interfaces of these use-cases, repositories, or databases, you need to run the corresponding command to regenerate the mock code for testing.
.
├── Dockerfile
├── api
│ ├── controller
│ │ ├── login_controller.go
│ │ ├── profile_controller.go
│ │ ├── profile_controller_test.go
│ │ ├── refresh_token_controller.go
│ │ ├── signup_controller.go
│ │ └── task_controller.go
│ ├── middleware
│ │ └── jwt_auth_middleware.go
│ └── route
│ ├── login_route.go
│ ├── profile_route.go
│ ├── refresh_token_route.go
│ ├── route.go
│ ├── signup_route.go
│ └── task_route.go
├── bootstrap
│ ├── app.go
│ ├── database.go
│ └── env.go
├── cmd
│ └── main.go
├── docker-compose.yaml
├── domain
│ ├── error_response.go
│ ├── jwt_custom.go
│ ├── login.go
│ ├── profile.go
│ ├── refresh_token.go
│ ├── signup.go
│ ├── success_response.go
│ ├── task.go
│ └── user.go
├── go.mod
├── go.sum
├── internal
│ └── tokenutil
│ └── tokenutil.go
├── mongo
│ └── mongo.go
├── repository
│ ├── task_repository.go
│ ├── user_repository.go
│ └── user_repository_test.go
└── usecase
├── login_usecase.go
├── profile_usecase.go
├── refresh_token_usecase.go
├── signup_usecase.go
├── task_usecase.go
└── task_usecase_test.go
-
signup
- Request
curl --location --request POST 'http://localhost:8080/signup' \ --data-urlencode '[email protected]' \ --data-urlencode 'password=test' \ --data-urlencode 'name=Test Name'
- Response
{ "accessToken": "access_token", "refreshToken": "refresh_token" }
-
login
- Request
curl --location --request POST 'http://localhost:8080/login' \ --data-urlencode '[email protected]' \ --data-urlencode 'password=test'
- Response
{ "accessToken": "access_token", "refreshToken": "refresh_token" }
-
profile
- Request
curl --location --request GET 'http://localhost:8080/profile' \ --header 'Authorization: Bearer access_token'
- Response
{ "name": "Test Name", "email": "[email protected]" }
-
task create
- Request
curl --location --request POST 'http://localhost:8080/task' \ --header 'Authorization: Bearer access_token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'title=Test Task'
- Response
{ "message": "Task created successfully" }
-
task fetch
- Request
curl --location --request GET 'http://localhost:8080/task' \ --header 'Authorization: Bearer access_token'
- Response
[ { "title": "Test Task" }, { "title": "Test Another Task" } ]
-
refresh token
- Request
curl --location --request POST 'http://localhost:8080/refresh' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'refreshToken=refresh_token'
- Response
{ "accessToken": "access_token", "refreshToken": "refresh_token" }