如何开始写一个完美的项目(gin脚手架)(项目通用)

首先新创建一个go项目

在main方法里可以

(1):加载配置

(2):初始化mysql连接

(3):路由注册

(4):优雅关闭

1:加载配置

(1)新建一个目录conf,创建一个config.yaml用来存放配置静态资源

如mysql连接信息

mysql:
  host: "127.0.0.1"
  port: 3306
  user: "root"
  password: "root"
  db: "dbname"
  max_open_connection: 20
  max_idle_connection: 10

(2)新建一个目录setting,创建一个setting.go用来读取配置文件(建议用Viper,go语言配置神器)

func Init() (err error) {
	viper.SetConfigName("config")  // 指定配置文件名称(不需要带后缀)
	viper.SetConfigType("yaml")    // 指定配置文件类型(注意,远程)
	viper.AddConfigPath("./conf/") // 指定查找配置文件的路径(这里使用相对路径)
	err = viper.ReadInConfig()     // 读取配置信息
	if err != nil {
		fmt.Printf("viper.ReadInConfig() failed, err: %v\n", err)
		return
	}
	
	viper.WatchConfig() //热加载,实时监控配置文件的变化
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("configure file changed ...")
	})
	return
}
(3)在main方法直接调用
//1:加载配置
if err := settings.Init(); err != nil {
   fmt.Printf("init settings failed, err: %v\n", err)
   return
}

2:初始化mysql连接

(1)新建一个目录db,创建一个mysql.go用来初始化mysql连接,也是用Viper读取配置信息

func Init() (err error) {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True",
		viper.GetString("mysql.user"),
		viper.GetString("mysql.password"),
		viper.GetString("mysql:host"),
		viper.GetString("mysql.port"),
		viper.GetString("mysql.db"),
	)
	db, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		zap.L().Error("connect DB failed", zap.Error(err))
		return
	}
	db.SetMaxOpenConns(viper.GetInt("sql.max_open_connection"))
	db.SetMaxIdleConns(viper.GetInt("sql.max_idle_connection"))
	return
}

func Close() {
	err := db.Close()
	if err != nil {
		zap.L().Error("Closed mysql database failed", zap.Error(err))
		return
	}
	return
}
(2)在main方法直接调用
//2:初始化mysql连接
if err := mysql.Init(settings.Conf.MySQLConfig); err != nil {
   fmt.Printf("init mysql failed, err: %v\n", err)
   return
}
defer mysql.Close()

3:路由注册

(1)新建一个目录rooter,创建一个rooter.go用来写路由

func Setup() *gin.Engine {
	r := gin.Default()//使用gin默认内置的logger和Recovery中间件
	r.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, "ok")
	})
//可以继续接口函数...
	return r
}
(2)在main方法直接调用
//3:注册路由
r := rooter.Setup()

4:优雅关闭

//(1):在main方法写一个go协程
//4:启动服务(优雅关机)
	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", viper.GetInt("app.port")),
		Handler: r,
	}
	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) // 此处不会阻塞
	<-quit                                               // 阻塞在此,当接收到上述两种信号时才会往下执行
	zap.L().Info("Shutdown Server ...")
	// 创建一个 5 秒超时 context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	// 五秒内优雅关闭服务(将未处理完的请求处理完再关闭服务),超出 5 秒就超时退出
	if err := srv.Shutdown(ctx); err != nil {
		zap.L().Fatal("Server Shutdown: ", zap.Error(err))
	}
	zap.L().Info("Server exiting ...")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值