GoWeb脚手架的搭建

以下内容搭建一个Go Web较为通用的脚手架模板,使用CLD分层模式
在这里插入图片描述
一、加载配置文件

1、增加conf.yaml文件

app:
  name: "web_app"
  mode: "dev"
  port: 8080
log:
  level: "debug"
  filename: "conf"
  max_size: 200
  max_age: 30
  max_backups: 7
mysql:
  host: "127.0.0.1"
  port: "3306"
  user: "root"
  password: "root"
  dbname: "Test"
redis:
  host: "127.0.0.1"
  port: 6379

2、新建setting包将配置绑定结构体

package setting
import (
   "fmt"
   "github.com/fsnotify/fsnotify"
   "github.com/spf13/viper"
)
type Config struct{
   App
   Log
   Mysql
   Redis
}
type App struct{
   Name string `mapstructure:"name"`
   Mode string `mapstructure:"mode"`
   Port int    `mapstructure:"port"`
}
type Log struct{
   Level string      `mapstructure:"level"`
   Filename string   `mapstructure:"filename"`
   Max_size int      `mapstructure:"max_size"`
   Max_age int       `mapstructure:"max_age"`
   Max_backups int   `mapstructure:"max_backups"`
}
type Mysql struct{
   Host string       `mapstructure:"host"`
   Port int          `mapstructure:"port"`
   User string       `mapstructure:"user"`
   Password string   `mapstructure:"password"`
   Dbname string     `mapstructure:"dbname"`
}
type Redis struct{
   Host string       `mapstructure:"host"`
   Port int          `mapstructure:"port"`
}
var Conf =&Config{}
func InitConfig(){
   viper.SetConfigName("conf")
   viper.AddConfigPath("Conf")
   err:=viper.ReadInConfig()
   if err!=nil{
      if v,ok:=err.(viper.ConfigFileNotFoundError);ok{
         fmt.Println(v)
      }else{
         panic(fmt.Errorf("read config err=%s",err))
      }
   }
   err=viper.Unmarshal(Conf)
   if err!=nil{
      fmt.Println("This Unmarshal Err",err)
      return
   }
   viper.WatchConfig()
   viper.OnConfigChange(func(in fsnotify.Event) {
      //Can Add Some Logics
      fmt.Println("Config Was Changed",in.Name)
   })
}

二、初始化配置文件

1、初始化日志log(zap日志系统)

所需要的配置信息尽量从配置中获取,不直接设置

package Log

import (
	"GinFrameDemo/setting"
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var logger *zap.Logger  //global variable

func InitLog(){
	encoder:=getEncoder()
	writer:=getWriter()
	core:=zapcore.NewCore(encoder,writer,zapcore.DebugLevel)  //get core,this is New method first param
	logger=zap.New(core,zap.AddCaller())   //return my logger
}
func getEncoder() zapcore.Encoder{
	encoderConfig := zap.NewProductionEncoderConfig()   		//Add Encoding Config
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder  		//Add Time Config
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder  	//Add Big Writer
	return zapcore.NewJSONEncoder(encoderConfig)  				//return core Add encoderConfig,ago Add zap.NewProductionEncoderConfig()
}
func getWriter()zapcore.WriteSyncer{
	lumberJackLogger := &lumberjack.Logger{
		Filename:   setting.Conf.Filename,
		MaxSize:    setting.Conf.Max_size,      	//one Max Size
		MaxBackups: setting.Conf.Max_backups,      	//beifen
		MaxAge:     setting.Conf.Max_age,   		//this time
		Compress:   setting.Conf.IsCompress,   		//zip
	}
	return zapcore.AddSync(lumberJackLogger)
}

注意:可能会使用gcc,需要在linux中下载gcc

sudo apt install gcc

2、初始化mysql配置

var DB *gorm.DB

func InitMysql(){
	var err error
	//dsn:="UserName:password@tcp(ip:port)/databaseName?charset=utf8mb4&parseTime=true&loc=local"
	dsn := "root:root@tcp(127.0.0.1:3306)/testgorm?charset=utf8mb4&parseTime=True&loc=Local"
	DB,err=gorm.Open(mysql.Open(dsn),&gorm.Config{})    //Open the Database
	if err!=nil{
		Log.Logger.Error("Gorm Open Error", zap.Error(err))
	}
}

3、初始化redis操作

var (
	rdb *redis.Client
)
func InitRedis() (err error) {
	rdb = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "root",  // password
		DB:       0,   // use default DB
		PoolSize: 100, // Redis Pool Size
	})
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	_, err = rdb.Ping(ctx).Result()
	return err
}

注意:替换全局的logger

三、注册路由

将Gin中注册路由信息,返回r

//RegisterRouter
    r:=Router.SetUpRouter()   //Register Router IN This
//在Router包中
package Router

import (
    "GinFrameDemo/Log"
    "github.com/gin-gonic/gin"
)

func SetUpRouter() *gin.Engine{
    r:=gin.New()   //if use Default ,will use default`s Router and middleware
    r.Use(Log.GinLogger(),Log.GinRecovery(true))
    r.GET("/", func(c *gin.Context) {
        c.JSON(200,gin.H{
            "message":"hello gin",
        })
    })
    return r
}
注意:注册zap的log中间件在gin中

四、优雅关机与平滑重启

默认路由

func SetUpRouter() *gin.Engine{
    r:=gin.New()   //if use Default ,will use default`s Router and middleware
    r.Use(Log.GinLogger(),Log.GinRecovery(true))
    r.GET("/", func(c *gin.Context) {
        c.JSON(200,gin.H{
            "message":"hello gin",
        })
    })
    return r
}

设置路由并且设置平滑开机与重启

	//RegisterRouter
    r:=Router.SetUpRouter()   //Register Router IN This
	//StartService
	srv:=&http.Server{
		Addr: fmt.Sprintf("%d",setting.Conf.App.Port), 		// Listen TCP Adress,if eq nil ,will become ":http"
		Handler: r,     	// Is Controller,if eq nil will call http.DefaultServeMux
	}
	go func(){
		if err:=srv.ListenAndServe();err!=nil&&err!=http.ErrServerClosed{
			log.Fatalf("Listen is %s",err)
		}
	}()     //New goroutine Listen Get conn
	quit:=make(chan os.Signal,1)      //Create a Chanel Get Sign
	//First Send syscall.SIGTERM
	//Syscall.SIGINT Like Ctrl+C
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)   //Mustbe Get All Sign
	<-quit
	log.Println("Shutdown Server ...")   //When Get SignInt  Start Kill
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)   //Set 5s After Kill
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {    //Beatiful Abort
		log.Fatal("Server Shutdown: ", err)
	}
	log.Println("Server exiting")

如果看完这篇文章对自己有所帮助,请点赞支持,谢谢大家