36-搭建通用web开发脚手架

在这里插入图片描述

脚手架目录结构

1、配置管理

项目目录下创建setting/setting.go:

package setting

import (
	"fmt"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

// Conf 定义配置的全局变量
var Conf = new(AppConfig)

type AppConfig struct {
	Name      string `mapstructure:"name"`
	Mode      string `mapstructure:"mode"`
	Version   string `mapstructure:"version"`
	StartTime string `mapstructure:"start_time"`
	MachineID int64  `mapstructure:"machine_id"`
	Port      int    `mapstructure:"port"`

	*LogConfig   `mapstructure:"log"`
	*MySQLConfig `mapstructure:"mysql"`
	*RedisConfig `mapstructure:"redis"`
}

type MySQLConfig struct {
	Host         string `mapstructure:"host"`
	User         string `mapstructure:"user"`
	Password     string `mapstructure:"password"`
	DB           string `mapstructure:"dbname"`
	Port         int    `mapstructure:"port"`
	MaxOpenConns int    `mapstructure:"max_open_conns"`
	MaxIdleConns int    `mapstructure:"max_idle_conns"`
}

type RedisConfig struct {
	Host         string `mapstructure:"host"`
	Password     string `mapstructure:"password"`
	Port         int    `mapstructure:"port"`
	DB           int    `mapstructure:"db"`
	PoolSize     int    `mapstructure:"pool_size"`
	MinIdleConns int    `mapstructure:"min_idle_conns"`
}

type LogConfig struct {
	Level      string `mapstructure:"level"`
	Filename   string `mapstructure:"filename"`
	MaxSize    int    `mapstructure:"max_size"`
	MaxAge     int    `mapstructure:"max_age"`
	MaxBackups int    `mapstructure:"max_backups"`
}

// 配置相关

// Init 配置初始化
func Init(filePath string) (err error) {
	// 指定配置文件路径
	viper.SetConfigFile(filePath)
	// 读取配置信息
	err = viper.ReadInConfig()
	if err != nil {
		// 读取配置信息失败
		fmt.Printf("viper.ReadInConfig failed, err:%v\n", err)
		return
	}

	// 把读取到的配置信息反序列化到 Conf 变量中
	if err := viper.Unmarshal(Conf); err != nil {
		fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		return err
	}
	// 监听配置文件变化
	viper.WatchConfig()

	// 当使用结构体变量存储配置的时候,需要在配置发生变更后手动更新一下结构体变量
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("配置文件修改了...")
		if err := viper.Unmarshal(Conf); err != nil {
			fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		}
	})
	return nil
}

在conf/conf.yaml配置:

name: myapp
mode: dev
version: "1.0"
port: 8099

log:
  level: debug
  filename: myapp.log
  max_size: 400
  max_age: 30
  max_backups: 15

  mysql:
    host: 127.0.0.1
    port: 3306
    user: root
    password: root1234
    db: db1
    MaxOpenConns: 20
    MaxIdleConns: 2
2、logger从配置文件读取

Logger/logger.go

package logger

import (
	"gin_zap/setting"
	"strings"

	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// initlogger 初始化日志
func Init() (err error) {
	// 1、encoder
	encndercfg := zap.NewProductionEncoderConfig()
	encndercfg.TimeKey = "time"                          // 改变时间的key
	encndercfg.EncodeTime = zapcore.ISO8601TimeEncoder   // 更改时间格式
	encndercfg.EncodeLevel = zapcore.CapitalLevelEncoder //将日志级别大写并带有颜色
	enconder := zapcore.NewJSONEncoder(encndercfg)

	// 2、writerSyncer 将日志写到文件和终端
	lumberJackLogger1 := &lumberjack.Logger{
		Filename:   setting.Conf.LogConfig.Filename, // 从配置文件读取
		MaxSize:    setting.Conf.LogConfig.MaxSize,
		MaxBackups: setting.Conf.LogConfig.MaxBackups,
		MaxAge:     setting.Conf.LogConfig.MaxAge,
		Compress:   false,
	}

	lumberJackLogger2 := &lumberjack.Logger{
		Filename:   strings.Replace(setting.Conf.LogConfig.Filename, ".log", "_err.log", 1),
		MaxSize:    setting.Conf.LogConfig.MaxSize,
		MaxBackups: setting.Conf.LogConfig.MaxBackups,
		MaxAge:     setting.Conf.LogConfig.MaxAge,
		Compress:   false,
	}
	// 3、设置loglevel
	level, _ := zapcore.ParseLevel(setting.Conf.LogConfig.Level) // 从配置文件中读取

	// 创建zapcore
	core1 := zapcore.NewCore(enconder, zapcore.AddSync(lumberJackLogger1), level)
	core2 := zapcore.NewCore(enconder, zapcore.AddSync(lumberJackLogger2), zapcore.ErrorLevel) // 将error级别的log单独放在一个文件
	core := zapcore.NewTee(core1, core2)
	// 创建logger
	logger := zap.New(core)

	// 替换zap全局的logger
	zap.ReplaceGlobals(logger)
	zap.L().Info(" logger init success")
	return

}
3、数据库初始化

Dao/mysql.go

package dao

// 将之前数据库连接代码写进去
func Init() error {
	return nil
}
4、路由初始化

router/router.go

package router

import (
	"gin_zap/middleware"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func Init() *gin.Engine {
	r := gin.New()
	r.Use(middleware.GinLogger(zap.L()), middleware.GinRecovery(zap.L(), true))
	r.GET("/littleboy", func(c *gin.Context) {
		zap.L().Info("返回一条日志")
	})

	return r

}

5、路由启动
r.Run()
6、main函数启动
package main

import (
	"fmt"
	"gin_zap/dao"
	"gin_zap/logger"
	"gin_zap/router"
	"gin_zap/setting"
	"os"

	"go.uber.org/zap"
)

func main() {

	// 1、加载配置
	if len(os.Args) < 2 {
		panic("执行时必须指定参数")
	}
	err := setting.Init(os.Args[1])
	if err != nil {
		panic(err)
	}
	fmt.Println(setting.Conf.Name)

	// 2、 加载日志模块
	err = logger.Init()
	if err != nil {
		panic(err)
	}

	// 3、数据库初始化

	err = dao.Init()
	if err != nil {
		zap.L().Error("mysql connect error")
	}

	// 4、路由初始化
	r := router.Init()
	// 5、程序启动
	r.Run()
}

代码层级结构 CLD分层

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值