Golang REST API boilerplate
Tags: go, restapi, webdev
Published: 2024-06-04 20:58:49


Upon meticulous investigation into the top Golang RESTful API project architectures, I have discovered that the Goffers community shares a number of common structures. I'll share my decision with you along with a boilerplate that makes use of **MongoDB** and the **Golang Echo framework**.
## 1. Project initialization

First we need to initialize golang project with :

```
$ go mod init github.com/HichOoMa/golang-boilerplate
```

this command will init go modules and help you to manage your project dependencies

## 2. Files Structure

This the folder structure of the code that I used to work with

```

.
└── golang-boilerplate
	├── cmd
	│ ├── api
	│ │ └── main.go
	│ └── ...
	├── api
	│ ├── handlers
	│ ├── middlewares
	│ ├── routes
	│ └── init.go
	├── assets
	│ └── ...
	├── internal
	│ ├── app
	│ │ ├── config
	│ │ ├── database
	│ │ ├── models
	│ │ ├── enums
	│ │ ├── business
	│ │ └── ...
	│ └── lib
	│ └── ...
	├── pkg
	│ ├── cloud
	│ ├── jwt
	│ ├── mailer
	│ └── ...
	├── test
	│ └── ...
	├── go.mod
	├── go.sum
	└── Makerfile
```

### a. `/cmd`

In a Go project, the "cmd" folder is a commonly used convention for organizing the entry points or main packages of your application. It stands for "command" and is typically used to house executable commands or programs within your project.

The purpose of organizing your main packages under "cmd" is to separate them from the reusable packages stored in the "pkg" or "internal" directories. This makes it clearer which parts of your code base are intended to be standalone commands or programs versus shared libraries or packages.

Using the "cmd" folder structure also aligns well with the Go ecosystem's conventions for package organization and helps keep your project modular and maintainable.

### b. `/api`

The api folder contain the necessary element of the owr API such as handlers, middelware and routes
#### Server Creation

In the first place we need to create our TCP server to listen for the HTTP requests coming to own local port. As we already mentioned we will use Echo framework.

We need first to install our dependencies :
```
$ go get github.com/labstack/echo/v4
```

Then we can start our server by creating our `init()` function in `api/init.go`
```go
package api

import (
	"net/http"
	"github.com/labstack/echo/v4"
)

func init() {
	e := echo.New()
	// add server routes and middleware
	e.Logger.Fatal(e.Start(":1323"))
}
```

Now we are listning to encoming request on `localhost:1323`
#### `/handlers`

In REST API projects, the "handlers" folder is commonly used to organize HTTP request handlers or controllers. This folder typically contains Go files that define the logic for handling incoming HTTP requests, parsing request parameters, validating input, interacting with the database, and returning responses.

This is a base example of an echo framework handler
```go
func hello(c echo.Context) error {
	// you can do some business here
	return c.String(http.StatusOK, "Hello, World!")
}
```
#### `/middlewares`

Also the middlewares is commonly used to organize HTTP Request and add layers to specific routes for different reasons such as security, presentations, error handling, ...

  

```go
func helloMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
	return func(c echo.Context) error {
		// do some business here
		return next(c)
	}
}
```

#### `/routes`

Routes is the part of code that attach path ( "/example", "/order/edit", ... ) with middlewares and handlers to process HTTP request requests.

> it can be just a file or part of the init function if own app contain a small number of routes

```go
e.GET("/status", getOrder)
e.POST("/order", createOrder)
e.PUT("/hello", updateOrder)
e.DELETE("/hello", deleteOrder)
```
### c. `/assets

You can store any assets or resources you need it in you application such as images, csv files, logos, etc
### d. `/internal`

This folder contain mainly private application and library code. This is the code you don't want others importing in their applications or libraries. Note that this layout pattern is enforced by the Go compiler itself. See the Go 1.4 [`release notes`](https://golang.org/doc/go1.4#internalpackages) for more details. Note that you are not limited to the top level `internal` directory. You can have more than one `internal` directory at any level of your project tree.

You can optionally add a bit of extra structure to your internal packages to separate your shared and non-shared internal code. It's not required (especially for smaller projects), but it's nice to have visual clues showing the intended package use. Your actual application code can go in the `/internal/app` directory (e.g., `/internal/app/myapp`) and the code shared by those apps in the `/internal/pkg` directory (e.g., `/internal/pkg/myprivlib`).

Examples:
* https://github.com/hashicorp/terraform/tree/main/internal
* https://github.com/influxdata/influxdb/tree/master/internal
* https://github.com/perkeep/perkeep/tree/master/internal
* https://github.com/jaegertracing/jaeger/tree/main/internal
* https://github.com/moby/moby/tree/master/internal
* https://github.com/satellity/satellity/tree/main/internal
* https://github.com/minio/minio/tree/master/internal
#### `/internal/pkg`
Examples:
* https://github.com/hashicorp/waypoint/tree/main/internal/pkg
### e. `/pkg`

This one contain library code that's ok to use by external applications (e.g., `/pkg/jwt`). Other projects will import these libraries expecting them to work, so think twice before you put something here :-) Note that the `internal` directory is a better way to ensure your private packages are not importable because it's enforced by Go. The `/pkg` directory is still a good way to explicitly communicate that the code in that directory is safe for use by others. The [`I'll take pkg over internal`](https://travisjeffery.com/b/2019/11/i-ll-take-pkg-over-internal/) blog post by Travis Jeffery provides a good overview of the `pkg` and `internal` directories and when it might make sense to use them.

It's also a way to group Go code in one place when your root directory contains lots of non-Go components and directories making it easier to run various Go tools (as mentioned in these talks: [`Best Practices for Industrial Programming`](https://www.youtube.com/watch?v=PTE4VJIdHPg) from GopherCon EU 2018, [GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps](https://www.youtube.com/watch?v=oL6JBUk6tj0) and [GoLab 2018 - Massimiliano Pippi - Project layout patterns in Go](https://www.youtube.com/watch?v=3gQa1LWwuzk)).

Note that this is not a universally accepted pattern and for every popular repo that uses it you can find 10 that don't. It's up to you to decide if you want to use this pattern or not. Regardless of whether or not it's a good pattern more people will know what you mean than not. It might a bit confusing for some of the new Go devs, but it's a pretty simple confusion to resolve and that's one of the goals for this project layout repo.

Ok not to use it if your app project is really small and where an extra level of nesting doesn't add much value (unless you really want to). Think about it when it's getting big enough and your root directory gets pretty busy (especially if you have a lot of non-Go app components).

The `pkg` directory origins: The old Go source code used to use `pkg` for its packages and then various Go projects in the community started copying the pattern (see [`this`](https://twitter.com/bradfitz/status/1039512487538970624) Brad Fitzpatrick's tweet for more context).

Examples :
* https://github.com/containerd/containerd/tree/main/pkg
* https://github.com/slimtoolkit/slim/tree/master/pkg
* https://github.com/telepresenceio/telepresence/tree/release/v2/pkg

### f. `/test`

Additional external test apps and test data. Feel free to structure the `/test` directory anyway you want. For bigger projects it makes sense to have a data subdirectory. For example, you can have `/test/data` or `/test/testdata` if you need Go to ignore what's in that directory. Note that Go will also ignore directories or files that begin with "." or "_", so you have more flexibility in terms of how you name your test data directory.

Examples:
* https://github.com/openshift/origin/tree/master/test (test data is in the `/testdata` subdirectory)