基本框架最佳实践及脚手架
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:
- define by interface
- add real implement or mock
- 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