适用于初学Gin的web脚手架

GIN_WEB脚手架

​ 笔者刚刚完成了七米老师的Gin框架学习并受益良多。为了帮助和我一样的Go语言小白,我将学习到的基于CLD层次的Gin脚手架分享给大家,帮助大家学习使用

开源地址

GIN_WEB脚手架

项目亮点

  • CLD目录架构
  • Air热更新 教程链接: > github.com/cosmtrek/ai…
  • Viper动态读取配置
  • 优雅关机
  • 项目结构

    ├── LICENSE
    ├── README.md
    ├── conf                           // 配置信息
    ├── controller                     // controller层,用来储存路由对应的处理函数
    ├── dao                                                      // dao层,包含数据库驱动和对数据库的crud操作
    ├── go.mod                                               
    ├── go.sum
    ├── logger                                               // zap日志库集合,用来代替Gin原始日志库
    ├── logic                          // logic层,包含对controller层中对应函数的业务实现
    ├── logs                                                     // 记录日志
    ├── main.go                        // 主函数
    ├── middlewares                    // 中间件
    ├── models                         // 模型层
    ├── pkg                            // 一些处理包,诸如jwt和雪花算法
    ├── routes                         // 路由
    ├── settings                       // 设置,用来读取配置
    
    

    功能介绍

    config.yaml

    配置信息,开发人员可以在里面配置开发信息。例如项目运行端口、mysql配置和日志保存配置

    name: "Gin_app"
    mode: "dev"
    port: 8082
    start_time: "2021-01-01"
    machine_id: 1
    
    log:
      level: "debug"
      filename: "./logs/gin_app.log"
      maxsize: 200
      maxbackups: 10
      maxage: 30
    
    mysql:
      host: "127.0.0.1"
      port: "13306"
      user: "root"
      password: "123456"
      dbname: "Gin_app"
    redis:
      host: "127.0.0.1"
      port: 6379
      db: 0
      password: ""
      poolsize: 100
    

    main.go

    主函数

  • 加载配置
  • 初始化日志
  • 初始化数据库链接
  • 初始化雪花算法
  • 初始化Gin框架内置的校验器翻译器
  • 优雅关机
  • package main
    
    import (
        "Gin_Web_demo/controller"
        "Gin_Web_demo/dao/mysql"
        "Gin_Web_demo/dao/redis"
        "Gin_Web_demo/logger"
        "Gin_Web_demo/pkg/snowflake"
        "Gin_Web_demo/routes"
        "Gin_Web_demo/settings"
        "context"
        "fmt"
        "go.uber.org/zap"
        "log"
        "net/http"
        "os"
        "os/signal"
        "syscall"
        "time"
    )
    
    func main() {
        // 1. 加载配置
        if err := settings.Init(); err != nil {
            fmt.Printf("init settings failed, err:%v\n", err)
            return
        }
        fmt.Println(settings.Conf)
        // 2. 初始化日志
        if err := logger.Init(settings.Conf.LogConfig, settings.Conf.Mode); err != nil {
            fmt.Printf("init logger failed, err:%v\n", err)
            return
        }
        defer zap.L().Sync()
        zap.L().Debug("logger init success...")
        // 3. 初始化MySQL连接
        if err := mysql.Init(settings.Conf.MySQLConfig); err != nil {
            fmt.Printf("init mysql failed, err:%v\n", err)
            return
        }
        defer mysql.Close()
        // 4. 初始化Redis连接
        if err := redis.Init(settings.Conf.RedisConfig); err != nil {
            fmt.Printf("init redis failed, err:%v\n", err)
            return
        }
        defer redis.Close()
        // 5. 初始化雪花算法
        if err := snowflake.Init(settings.Conf.StartTime, settings.Conf.MachineID); err != nil {
            fmt.Printf("init snowflake failed, err:%v\n", err)
            return
        }
        // 6. 初始化Gin框架内置的校验器翻译器
        if err := controller.InitTrans("zh"); err != nil {
            fmt.Printf("init validator trans err:%v\n", err)
            return
        }
        // 7. 注册路由
        r := routes.Setup(settings.Conf.Mode)
        // 8. 启动服务(优雅关机)
        srv := &http.Server{
            Addr:    fmt.Sprintf(":%d", settings.Conf.Port),
            Handler: r,
        }
        // 打印启动端口
        fmt.Printf("启动端口: %d\n", settings.Conf.Port)
        go func() {
            // 开启一个goroutine启动服务
            if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
                log.Fatalf("listen: %s\n", err)
            }
        }()
    
        // 等待中断信号来优雅地关闭服务器,为关闭服务器操作设置一个5秒的超时
        quit := make(chan os.Signal, 1) // 创建一个接收信号的通道
        // kill 默认会发送 syscall.SIGTERM 信号
        // kill -2 发送 syscall.SIGINT 信号,我们常用的Ctrl+C就是触发系统SIGINT信号
        // kill -9 发送 syscall.SIGKILL 信号,但是不能被捕获,所以不需要添加它
        // signal.Notify把收到的 syscall.SIGINT或syscall.SIGTERM 信号转发给quit
        signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 此处不会阻塞