It is hard to write bootstrap tool to quickly create Go service.
So I write this guide instead.
This is a quick checklist for me every damn time I need to write a Go service from scratch.
Also, this is my personal opinion, so feel free to comment.
## Structure
```txt
main.go
internal
| business_1
| | http
| | | handler.go
| | | service.go
| | | repository.go
| | | models.go
| | grpc
| | | handler.go
| | | service.go
| | | repository.go
| | | models.go
| | service.go
| | repository.go
| | models.go
| business_2
| | grpc
| | | handler.go
| | | service.go
| | | repository.go
| | | models.go
```
All business codes are inside `internal`.
Each business has a different directory (`business_1`, `business_2`).
Inside each business, there are 2 handlers: `http`, `grpc`:
-`http` is for public APIs (Android, iOS,... are clients).
-`grpc` is for internal APIs (other services are clients).
Inside each handler, there are usually 3 layers: `handler`, `service`, `repository`:
-`handler` interacts directly with gRPC or REST using specific codes (cookies,...)
-`service` is where we write business/logic codes, and only business/logic codes is written here.
-`repository` is where we write codes which interacts with database/cache like MySQL, Redis, ...
`handler` must exist inside `grpc`, `http`.
But `service`, `repository`, `models` can exist directly inside `business` if both `grpc`, `http` has same business/logic.
## Do not repeat!
If we have too many services, some of the logic will be overlapped.
For example, service A and service B both need to make POST call API to service C.
If service A and service B both have libs to call service C to do that API, we need to move the libs to some common pkg libs.
So in the future, service D which needs to call C will not need to copy libs to handle service C api but only need to import from common pkg libs.
Another bad practice is adapter service.
No need to write a new service if what we need is just common pkg libs.
## External libs
### Don't use cli libs ([spf13/cobra](https://github.com/spf13/cobra), [urfave/cli](https://github.com/urfave/cli)) just for Go service
What is the point to pass many params (`--abc`, `--xyz`) when what we only need is start service?
In my case, service starts with only config, and config should be read from file or environment like [The Twelve Factors](https://12factor.net/) guide.
### Don't use [grpc-ecosystem/grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway)
Just don't.
Use [protocolbuffers/protobuf-go](https://github.com/protocolbuffers/protobuf-go), [grpc/grpc-go](https://github.com/grpc/grpc-go) for gRPC.
Write 1 for both gRPC, REST sounds good, but in the end, it is not worth it.