Goscription
Goscription is skeleton project with simple design & clean code with Go
Install / Use
/learn @kecci/GoscriptionREADME
Goscription
Goscription is a sample of template RESTful API Project
Features
Some features & libraries used on this template:
- REST API (labstack/echo)
- Dependency Injection (uber-go/fx)
- NSQ Messaging (segmentio/nsq-go)
- Custom CLI (spf13/cobra)
- Custom Config File (spf13/viper)
- SQL Generator (squirrel)
- Migrations (go-migrate)
- Swagger API Docs Generator (swaggo/swag)
- Mock Generator (vektra/mockery)
- Custom Logger (sirupsen/logrus)
- Dockerize an Application (docker)
- Circuit Breaker (hystrix-go/hystrix && eapache/go-resiliency)
- Message Streams: Pub/Sub, Kafka, RabbitMQ, etc (ThreeDotsLabs/watermill) [Soon]
Installation
- Clone the Repos
$ git clone https://github.com/kecci/goscription.git
Command
This command is provided in Makefile. You can see all command with make:
$ make
Choose a command run in goscription:
mockery-prepare install mockery before generate
mockery-generate generate all mock
test-docker test docker integration
test-unit run all unit test
go-build build to compile the project & swagger docs
go-run run project
docker-build dockerize the project
docker-up run docker compose up
docker-down run docker compose down
swagger-init initialize swagger to folder ./docs
swagger-validate validate swagger.yaml in folder ./docs
migrate-prepare prepare migrate the schema with mysql
migrate-up run migration up to latest version
migrate-down run migration down to oldest version
Project Structure
.
├── app
│ ├── cmd
│ └── main.go
├── internal
│ ├── controller
│ ├── database
│ │ └── mysql
│ │ └── migrations
│ ├── middleware
│ ├── outbound
│ └── service
├── mocks
├── models
└── util
Dependency Injection
I found this library is very useful and you no need to generate anything. Just code. Very modular and clear layer.
uber-go/fx
A dependency injection based application framework for Go.
func main() {
fx.New(opts()).Run()
}
func opts() fx.Option {
return fx.Options(
fx.Provide(
NewTimeOutContext,
NewDbConn,
),
repository.Module, // Provide All Repository Module
service.Module, // Provide All Service Module
outbound.Module, // Provide All Outbound Module
server.Module, // Provide Runner/Stopper Server
fx.Invoke( // Invoke List of Controller
controller.InitFooController,
controller.InitBarController,
),
)
}
For more information about uber-go/fx: https://github.com/uber-go/fx
Config Properties
spf13/viper
Viper is a complete configuration solution for Go applications. viper can reading from:
- JSON,
- TOML,
- YAML,
- HCL,
- INI,
- envfile, and
- Java properties config files
Reading Config Files:
viper.SetConfigName("config") // name of config file (without extension)
viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
viper.AddConfigPath("/etc/appname/") // path to look for the config file in
viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths
viper.AddConfigPath(".") // optionally look for config in the working directory
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
Use Value from Config:
viper.Get("name") // this would be "steve"
You can do a lot more with viper, see more the documetation: https://github.com/spf13/viper
TOML
We are using toml in this sample project, for example:
title="Configuration File for Goscription"
debug=true
contextTimeout="5"
[server]
address= ":9090"
[database]
host="mysql"
port="3306"
user="root"
pass="root"
name="article"
Swagger
swag UI
Because our project setup the path of swagger in: /swagger/*. You can access swagger UI in here: http://localhost:9090/swagger/index.html
swaggo/swag
Swag converts Go annotations to Swagger Documentation 2.0. We've created a variety of plugins for popular Go web frameworks. This allows you to quickly integrate with an existing Go project (using Swagger UI).
Supported Web Frameworks:
- gin
- echo
- buffalo
- net/http
swag annotation
Swag has handled your swagger docs. So you no longer need to write swagger.yml or swagger.json. What you need to do is just write annotations. This is an example:
// @title Blueprint Swagger API
// @version 1.0
// @description Swagger API for Golang Project Blueprint.
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.email martin7.heinz@gmail.com
// @license.name MIT
// @license.url https://github.com/MartinHeinz/go-project-blueprint/blob/master/LICENSE
// @BasePath /api/v1
func main() {
...
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
...
}
You can see more about swag annotation in here: https://github.com/swaggo/swag.
Benchmark
Using https://github.com/wg/wrk
Script:
wrk -t8 -c256 -d30s http://localhost:9090/health
Output:
Running 30s test @ http://localhost:9090/health
8 threads and 256 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 13.17ms 11.67ms 153.74ms 71.04%
Req/Sec 2.82k 660.71 6.40k 69.88%
675770 requests in 30.08s, 150.16MB read
Socket errors: connect 0, read 121, write 0, timeout 0
Requests/sec: 22464.24
Transfer/sec: 4.99MB
Sources
This template is inspired & modified from https://github.com/golangid/menekel
