go之curd项目搭建

go + gin + xorm + viper 搭建模板化curd
项目

config 配置中心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func init() {
viper.SetConfigName("db-test")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.SetDefault("data", "data")
}

func Load() error {
return viper.ReadInConfig()
}
func Store() error {
return viper.SafeWriteConfig()
}

func Register(module string, key string, value any) {
viper.SetDefault(module+"."+key, value)
}
func GetString(module string, key string) string {
return viper.GetString(module + "." + key)
}

func GetBool(module string, key string) bool {
return viper.GetBool(module + "." + key)
}
func GetInt(module string, key string) int {
return viper.GetInt(module + "." + key)
}

db

初始化配置

1
2
3
4
5
6
7
8
9
const MODULE = "database"

func init() {
config.Register(MODULE, "type", "mysql")
config.Register(MODULE, "url", "root:test@tcp(test:3306)/master?charset=utf8")
config.Register(MODULE, "debug", false)
config.Register(MODULE, "sync", true)
}

创建engine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

var Engine *xorm.Engine

func Open() error {
var err error
Engine, err = xorm.NewEngine(config.GetString(MODULE, "type"), config.GetString(MODULE, "url"))
if err != nil {
return err
}
if config.GetBool(MODULE, "debug") {
Engine.ShowSQL(true)
Engine.SetLogLevel(log.LOG_DEBUG)
}
if config.GetBool(MODULE, "sync") {
Engine.Sync2()
}
return nil
}
func Close() error {
return Engine.Close()
}

models

收集全部模型 用于初始化数据库

1
2
3
4
5
6
var models []any

func Register(m ...any) {
models = append(models, m...)
}

types

init

1
2
3
4
5
注册全部的模型 用于同步数据库
func init() {
db.Register(new(User), new(Password))
}

新建模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type User struct {
Id string `json:"id" xorm:"pk"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
CellPhone string `json:"cellPhone,omitempty"`
Admin bool `json:"admin,omitempty"`
Disable bool `json:"disable,omitempty"`
Create time.Time `json:"create,omitempty" xorm:"created"`
}

type Password struct {
Id string `json:"id" xorm:"pk"`
Password string `json:"password"`
}

api封装

统一router注册

1
2
3
4
func RegisterRoutes(group *gin.RouterGroup) {
UserRouter(group.Group("/user"))
}

不同模块的增删改查

走统一的curd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// @Summary 查询用户
// @Schemes
// @Description 查询用户
// @Tags user
// @Param search query curd.ParamList true "查询参数"
// @Accept json
// @Produce json
// @Success 200 {object} curd.ReplyList[types.User] 返回用户信息
// @Router /user/list [get]
func noopUserList() {}
func UserRouter(app *gin.RouterGroup) {
app.GET("/list", curd.AipList[types.User]())
}

swaggo 相关

引包

1
2
import "github.com/swaggo/gin-swagger" // gin-swagger middleware
import "github.com/swaggo/files" // swagger embed files

安装swag

1
2
$ go get -u github.com/swaggo/swag/cmd/swag

安装之后就可以通过swag init在项目目录生成docs文件夹

在 main.go 中导入刚才生成的 docs 包

1
2
3
import (
_ "test/docs"
)

添加注释

1
2
3
4
5
6
7
8
9
10
// @Summary 查询用户
// @Schemes
// @Description 查询用户
// @Tags user
// @Param search query curd.ParamList true "查询参数"
// @Accept json
// @Produce json
// @Success 200 {object} curd.ReplyList[types.User] 返回用户信息
// @Router /user/list [get]
func noopUserList() {}

配置文档handler

最后则是在 router 中增加 swagger 的 handler 了。

1
2
3
engine := gin.New()
engine.GET("swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

gin-gonic

初始化配置

1
2
3
4
5
6
7
8
9
10
11
12
func init() {
config.Register(MODULE, "port", 8081)
config.Register(MODULE, "debug", false)
config.Register(MODULE, "cors", false)
config.Register(MODULE, "gzip", true)
config.Register(MODULE, "https", "")
config.Register(MODULE, "cert", "")
config.Register(MODULE, "key", "")
config.Register(MODULE, "hosts", []string{})
config.Register(MODULE, "email", "")

}

启动服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

type Engine struct {
*gin.Engine
}

func CreateEngine() *Engine {
if !config.GetBool(MODULE, "debug") {
gin.SetMode(gin.ReleaseMode)
}

app := gin.New()
app.Use(gin.Recovery())
if config.GetBool(MODULE, "debug") {
app.Use(gin.Logger())
}
if config.GetBool(MODULE, "cors") {
c := cors.DefaultConfig()
c.AllowAllOrigins = true
c.AllowCredentials = true
app.Use(cors.New(c))
}
app.Use(sessions.Sessions("gin-test", cookie.NewStore([]byte("gin-test"))))
if config.GetBool(MODULE, "gzip") {
app.Use(gzip.Gzip(gzip.DefaultCompression))
}
return &Engine{app}
}

func (app *Engine) Serve() {
port := config.GetInt(MODULE, "port")
addr := ":" + strconv.Itoa(port)

err := app.Run(addr)
if err != nil {
fmt.Println(err)
}
}