基本架构
bluebell
├─ config.yaml #配置文件
├─ controllers #服务入口 负责处理路由 ,参数校验 请求转发
├─ dao #负责数据与存储相关功能
│ ├─ mysql
│ │ └─ mysql.go
│ └─ redis
│ └─ redis.go
├─ go.mod
├─ go.sum
├─ logger #日志
│ └─ logger.go
├─ logic #逻辑层 负责业务逻辑
├─ main.go #主文件
├─ models #模型
├─ pkg #第三方库
├─ routes #路由
│ └─ routes.go
├─ settings #配置相关属性
│ └─ settings.go
├─ web_app.log #日志输出
└─ yay_cli.exe
以前我们后端搭建采用的是MVC(Model-View-Controller
)模式去搭建。现在更多的是采用CLD( controllers-logic-dao
)模式去进行开发.
开始工作如下:
- 加载配置文件
- 初始化日志
- 初始化mysql连接
- 初始化redis连接
- 注册路由
- 启动服务(优雅关机)
配置文件
当项目逐渐开始变大的时候,你的很多配置类的信息都尽量写在一起,方便更改,查询
**建立 config.yaml
**
name: "web_app" #姓名
mode: "dev" #模式
port: 8081 #端口
log:
level: "debug" #日志文件的位置
filename: "web_app.log" #文件名字
max_size: 200 #在进行切割之前,日志文件的最大大小(以MB为单位)
max_age: 30 #保留旧文件的最大天数
max_backups: 7 #保留旧文件的最大个数
mysql:
host: "127.0.0.1" #数据库ip
port: 3306 #数据库端口
user: "root" #数据库用户名
password: "123456" #数据库密码
dbname: "test" #数据库名字
max_open_conns: 200 #设置与数据库建立连接的最大数目
max_idle_conns: 50 #设置连接池中的最大闲置连接数
redis:
host: "127.0.0.1" #地址
port: 6379 #端口
db: 0 # use default DB
password: "" #密码
pool_size: 100 #连接池大小
在go中常用的配置管理库就是viper。
建立 settings
文件夹,专门管理配置文件相关的信息
package settings
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
func Init() error {
viper.SetConfigFile("config.yaml") // 指定配置文件
viper.AddConfigPath(".") // 指定查找配置文件的路径
err := viper.ReadInConfig() // 读取配置信息
if err != nil {
// 读取配置信息失败
fmt.Printf("viper.ReadInConfig() Failed err:%v\n", err)
return err
}
//监控并重新读取配置文件
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
// 配置文件发生变更之后会调用的回调函数
fmt.Println("Config file changed:", e.Name)
})
return nil
}
相关教程:https://www.liwenzhou.com/posts/Go/viper_tutorial/
初始化日志
一个好的项目,需要日志记录项目中发生一切。方便后续查bug出现的地方。
go有自己默认的 logger
,用处比较局限!一般推荐使用 zap
库作为日志库使用。
Zap是非常快的、结构化的,分日志级别的Go日志库。
建立 logger
文件,负责处理日志
package logger
import (
"net"
"net/http"
"net/http/httputil"
"os"
"runtime/debug"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/natefinch/lumberjack"
"github.com/spf13/viper"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// InitLogger 初始化Logger
func Init() (err error) {
//配置分割文档的属性
writeSyncer := getLogWriter(
viper.GetString("log.filename"),
viper.GetInt("log.max_size"),
viper.GetInt("log.max_backups"),
viper.GetInt("log.max_go"),
)
//配置输出的格式
encoder := getEncoder()
//创建日志级别
var l = new(zapcore.Level)
err = l.UnmarshalText([]byte(viper.GetString("log.level")))
if err != nil {
return
}
//定制logger
core := zapcore.NewCore(encoder, writeSyncer, l)
lg := zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(lg) // 替换zap包中全局的logger实例,后续在其他包中只需使用zap.L()调用即可
return
}
//更改时间编码并添加调用者详细信息
func getEncoder() zapcore.Encoder {
<