基本框架最佳实践及脚手架

library选择(not why A not B problem, only just need one problem,familiar)

logger: zap
web framework: gin
orm: xorm
ioc framework: fx,支持开发模块化
ACL: casbin
kv: boltdb
process local cache with: go-cache,

test library

模块化

component:

  1. define by interface
  2. add real implement or mock
  3. inject interface by ioc framework (go.uber.org/fx)
use cache as and example

cache: define by interface

// Cache Cache
type Cache interface {
 Put(prefix, key string, value interface{})
 Get(prefix, key string) (interface{}, bool)
}
// Module Module
var Module = fx.Options(
    fx.Provide(NewCache))

then inject into container by

app := fx.New(logger.Module, database.Module, cache.Module, config.Module,
 dao.Module, handler.ModuleWithDep, router.Module, fx.Populate(&errC))

// test demo
app := fx.New(logger.Module, database.Module, config.Module, fx.Options(handler.ModuleWoDep, **user.TestModule**), router.Module, fx.Populate(&errC))

ioc to get it by constructor

// NewHandler NewHandler
func NewHandler(user user.Service, cache cache.Cache) *Handler {
 return &Handler{
  userSvc: user,
  cache:   cache,
 }
}

模块目录结构

├── project
│   ├── ReadMe.md
│   ├── cmd
│   │   ├── client
│   │   ├── cmd
│   │   └── main.go
│   ├── common // put cross-cutting edge module here
│   │   ├── cache
│   │   │   └── cache.go
│   │   ├── config
│   │   │   ├── cmd_flags.go
│   │   │   ├── config.go
│   │   │   ├── config_test.go
│   │   │   ├── define.go
│   │   │   └── test_data
│   │   │       ├── paas.yaml
│   │   │       └── paas_dev.yaml
│   │   ├── const.go
│   │   ├── database
│   │   │   └── db.go
│   │   ├── errors
│   │   │   └── error.go
│   │   └── logger
│   │       └── logger.go
│   ├── config
│   │   ├── ReadMe.md
│   │   ├── config.yaml
│   │   └── config_dev.yaml
│   ├── dao // all xorm db operation inside dao dir
│   │   ├── convert  // convert between struct
│   │   │   └── ReadMe.md
│   │   ├── export.go
│   │   ├── generate.sh
│   │   ├── internal
│   │   ├── models   // xorm reverse auto gen file and self added model
│   │   ├── templates // xorm reverse config inside 
│   │   │   └── goxorm
│   │   │       ├── config
│   │   │       └── struct.go.tpl
│   │   └── user   // example Dao
│   │       ├── dao.go  // define interface 
│   │       └── export.go
│   ├── doc  // put swagger definition inside
│   │   └── ReadMe.md 
│   ├── go.mod
│   ├── go.sum
│   ├── handler // web handler, mostly wrapper for module
│   │   ├── export.go
│   │   ├── helper
│   │   │   └── common.go
│   │   ├── test
│   │   │   └── test.go
│   │   └── user
│   ├── module // business logic module
│   │   ├── ReadMe.md
│   │   ├── base
│   │   │   ├── helper.go
│   │   │   └── service.go
│   │   ├── pam
│   │   └── user
│   │       ├── definition
│   │       │   └── service.go
│   │       ├── export.go
│   │       ├── impl
│   │       │   └── user_impl.go
│   │       └── mock
│   │           └── user_mock.go
│   └── router  // gin framework related
│       ├── middleware
│       │   ├── logger.go
│       │   └── request_id.go
│       └── router.go
├── test // integrate test inside
│   ├── ReadMe.md
│   ├── go.mod
│   └── simple_test.go
└── util
    ├── collection
    │   └── string.go
    └── go.mod

related library

require (
    github.com/gin-gonic/gin v1.3.0                  // web framework
    github.com/go-sql-driver/mysql v1.4.0
    github.com/go-xorm/xorm v0.7.1                // orm
    github.com/lib/pq v1.0.0
    github.com/mitchellh/mapstructure v1.1.2   // unmarshal
    github.com/spf13/pflag v1.0.3                     // cmd flag
    github.com/spf13/viper v1.3.1                     // configuration library satisfy 12app requirement
    go.uber.org/fx v1.8.0                                   // DI framework
    go.uber.org/zap v1.9.1                                // structured log library
    gopkg.in/yaml.v2 v2.2.2                              // config file format
)
reference

modern app基本要求 https://12factor.net/
模块化组织 https://zhuanlan.zhihu.com/p/39326315
日志 https://medium.com/@gosamv/using-gos-context-library-for-logging-4a8feea26690
https://medium.com/@iNatata/use-struct-as-enum-in-go-6a314ae78678