routing
This is relatively simple, is the role of the registration route
package route import ( "go_web_app/logger" "net/http" "github.com/gin-gonic/gin" ) func Setup() *gin.Engine { r := R.us (logger.ginlogger (), logger.ginRecovery (true)) r.git ("/", func(context *gin.Context) { context.String(http.StatusOK, "ok") }) return r }Copy the code
Start the process
This one was introduced earlier, which is a slightly more sophisticated and elegant reboot scheme,
SRV := &http.Server{Addr: ftt.sprintf (":%d", viper.getint ("app.port"))), Handler: R,} go func() {// Start a goroutine start service if err := srv.listenAndServe (); err ! = nil && err ! = http.ErrServerClosed { zap.L().Error("listen: %s\n", zap.error (err))}}() // Wait for an interrupt signal to gracefully shut down the server, Quit := make(chan os.signal, Syscall. SIGTERM // kill -2 sends syscall.SIGINT, // Syscall.SIGKILL -9 sends the syscall.SIGKILL signal, but it cannot be captured. SIGINT (quit, syscall.sigint, syscall.sigterm, syscall.sigterm, syscall.sigterm, Syscall.sigterm) // will not block here <-quit // will block here Zap.l ().info ("Shutdown server") // Create a context CTX with a timeout of 5 seconds, Cancel := context.withtimeout (context.background (), 5* time.second) defer cancel() // Gracefully close the service within 5 seconds. If err := srv.Shutdown(CTX); err ! = nil { log.Fatal("Server Shutdown: ", err) zap.L().Error("Server Shutdown: ", zap.Error(err)) } zap.L().Info("Server exiting")Copy the code
Optimize the code. – DON’t expose the DB
In the previous code, it was not appropriate to expose the DB. The best solution is to provide a close method so that the method does not expose the DB
// initialize mysql if err := mysql.init (); err ! = nil { fmt.Printf("init mysql failed:%s \n", Err) return} zap.l ().debug ("mysql init success") // Initialize redis if err := redis.init (); err ! = nil { fmt.Printf("init redis failed:%s \n", err) return } defer mysql.Close() defer redis.Close()Copy the code
var db *sqlx.DB func Close() { _ = db.Close() } func Init() (err error) { dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s? charset=utf8mb4&parseTime=True", viper.GetString("mysql.user"), viper.GetString("mysql.password"), viper.GetString("mysql.host"), viper.GetInt("mysql.port"), viper.GetString("mysql.dbname"), ) // You can also use MustConnect to panic db, err = sqlx.Connect("mysql", DSN) if err! = nil { zap.L().Error("connect DB failed, err:%v\n", zap.Error(err)) return } db.SetMaxOpenConns(viper.GetInt("mysql.max_open_connection")) db.SetMaxIdleConns(viper.GetInt("mysql.max_idle_connection")) return }Copy the code
Optimized configuration item
The previous configuration items are fetched by string, which is not very readable. Now we need to find a way to convert config into a structure to handle this, so that the code will be more readable
type AppConfig struct {
Name string `mapstructure:"name"`
Mode string `mapstructure:"mode"`
Port int `mapstructure:"port"`
*LogConfig `mapstructure:"log"`
*MysqlConfig `mapstructure:"mysql"`
*RedisConfig `mapstructure:"redis"`
}
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"`
}
type MysqlConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
DbName string `mapstructure:"dbname"`
MaxOpenConnection int `mapstructure:"max_open_connection"`
MaxIdleConnection int `mapstructure:"max_idle_connection"`
}
type RedisConfig struct {
Host string `mapstructure:"host"`
Password string `mapstructure:"passowrd"`
Post int `mapstructure:"port"`
Db int `mapstructure:"db"`
PoolSize int `mapstructure:"pool_size"`
}
Copy the code
And then we change our viper reading process which is basically serialization
Var Config = new(AppConfig) // Init Load configuration file func Init() error {per.setConfigname (" Config ") // Name of configuration file Viper. setType ("yaml") // The extension of the configuration file. Err := per.readinConfig () if err! = nil {fmt.Println("viper init failed:", err) return err} if err := per.unmarshal (Config); err ! = nil { fmt.Println("viper Unmarshal err", Err)} per.watchConfig () per.onConfigChange (func(in fsnotify.event) {fmt.println (" Config file has been modified ")}) return err}Copy the code
Modify mysql init method to pass a mysql config parameter
func Init(config *setting.MysqlConfig) (err error) { dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s? charset=utf8mb4&parseTime=True", config.User, config.Password, config.Host, config.Port, config.DbName, Err := sqlx.Connect("mysql", DSN) if err! = nil { zap.L().Error("connect DB failed, err:%v\n", zap.Error(err)) return } db.SetMaxOpenConns(viper.GetInt("mysql.max_open_connection")) db.SetMaxIdleConns(viper.GetInt("mysql.max_idle_connection")) return }Copy the code
That’s all you need to use it
/ / initialized mysql if err: = mysql. The Init (setting. Config. MysqlConfig); err ! = nil { fmt.Printf("init mysql failed:%s \n", err) return }Copy the code
The source address