package main import ( "gen/config" "gen/router" "github.com/gin-gonic/gin" "log" ) func main() { gin.SetMode(getMode()) engine := gin.New() engine.Use(gin.Recovery()) // 堆代码 duidaima.com // 加载路由 router.Route(engine) // 启动服务器 log.Println("server started success") err := engine.Run(":" + config.GetAPP("PORT").String()) if err != nil { log.Fatalf("server start failed, error: %s", err.Error()) } } func getMode() string { debug := config.GetAPP("DEBUG").String() if debug == "true" { return gin.DebugMode } return gin.ReleaseMode }main里面第一步就是加载配置文件,然后根据配置文件设置Gin的模式以及服务监听的端口,然后这里还有一些”隐藏“的init初始化操作,比如在初始化路由的过程中加载了数据库配置并且建立数据库连接、还有初始化日志配置等,具体可以查看各个包的init函数。
[APP] PORT = 8080 DEBUG = true URL = http://127.0.0.1:8080 LOG_FILE = storage/logs/app.log LOG_LEVEL = info [DB] Dialect = mysql DSN = root:123456@tcp(127.0.0.1:3306)/blog?charset=utf8mb4&parseTime=True&loc=Local MAX_IDLE_CONN = 5 MAX_OPEN_CONN = 50加载配置文件的代码位于config/Config.go文件里面,逻辑非常简单,也支持通过”-c“指定配置文件,这里定义了一个包全局变量,一次加载,终身使用,具体的日志读取API可以参考这个库的官方文档。
func getContext(ctx *gin.Context) []zap.Field { var ( now = time.Now().Format("2006-01-02 15:04:05.000") processId = os.Getpid() startTime, _ = ctx.Get("startTime") duration = float64(time.Now().Sub(startTime.(time.Time)).Nanoseconds()/1e4) / 100.0 //单位毫秒,保留2位小数 serviceStart = startTime.(time.Time).Format("2006-01-02 15:04:05.000") request = ctx.Request.RequestURI hostAddress = ctx.Request.Host clientIp = ctx.ClientIP() traceId = ctx.GetString("traceId") parentId = ctx.GetString("parentId") params = ctx.Request.PostForm ) return []zap.Field{ zap.String("traceId", traceId), zap.String("serviceStart", serviceStart), zap.String("serviceEnd", now), zap.Int("processId", processId), zap.String("request", request), zap.String("params", params.Encode()), zap.String("hostAddress", hostAddress), zap.String("clientIp", clientIp), zap.String("parentId", parentId), zap.Float64("duration", duration)} }如果想记录当前请求的一些信息可以使用zlog.WithContext(ctx).Sugar().Infof("log msg")这种写法来记录,同理,详细API可以参考其官方文档。
package config var DBConfig map[string]map[string]string func init() { DBConfig = map[string]map[string]string{ "default": { "dialect": Conf.Section("DB").Key("Dialect").String(), "dsn": Conf.Section("DB").Key("DSN").String(), "maxIdleConns": Conf.Section("DB").Key("MAX_IDLE_CONN").String(), "maxOpenConns": Conf.Section("DB").Key("MAX_OPEN_CONN").String(), }, "user": { "dialect": Conf.Section("DB").Key("Dialect").String(), "dsn": Conf.Section("DB").Key("DSN").String(), "maxIdleConns": Conf.Section("DB").Key("MAX_IDLE_CONN").String(), "maxOpenConns": Conf.Section("DB").Key("MAX_OPEN_CONN").String(), }, } }然后在model/DB.go文件里面,初始化了所有的DB配置,并且提供一个快速访问的函数:
// 获取默认db func DB() *gorm.DB { conn, ok := dbConnections["default"] if !ok { return nil } return conn } // 获取user db func UserDB() *gorm.DB { conn, ok := dbConnections["user"] if !ok { return nil } return conn } // 获取db连接 func GetDB(name string) *gorm.DB { conn, ok := dbConnections[name] if !ok { return nil } return conn }关于gorm的详细用法可以参考其官方文档:https://gorm.io/
所以,从最佳实践上说,应该是controller调model,model调service这个顺序,不可反向操作。
最后,这个项目自带了一个包括用户注册登录以及发表文章、查看文章的API的功能,具体可以查看项目README文件,如果想使用的话建议直接clone本项目,然后在这个基础上修改。