接着上文继续开发,这一章主要是修改setting配置项。
之前的章节里面,其实我就注意到了。各个配置都到处散落着。
我们采用下面的方法来解决:
- 映射结构体:使用 MapTo设置配置参数
- 统一配置管理:所有的配置项都放到setting中。
重构setting包
1. 修改配置文件
修改conf/app.ini配置文件,修改如下:
- 文件名改为setting.ini
- 文件内容改为大驼峰命名法
- 增加日志配置项[Log]
- 增加RuntimeRootPath[app]
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
[app] PageSize = 10 JWTSecret = 23347$040412 RuntimeRootPath = runtime/ [log] SavePath = logs/ SaveName = log FileExt = log TimeFormat = 20060102 [server] #debug or release RunMode = debug HTTPPort = 8000 ReadTimeout = 60 WriteTimeout = 60 [mysql] User = xiong Password = xiong_pc Host = 192.168.1.101:3306 DBName = ginBlog TablePrefix = blog_ |
2. 修改setting包
修改setting/setting.go文件,内容如下:
P.S. 需要注意的是,结构体成员必须是导出的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
package setting import ( "log" "time" "github.com/go-ini/ini" ) //AppSection 配置文件 type AppSection struct { PageSize int `ini:"PageSize"` JWTSecret string `ini:"JWTSecret"` RuntimeRootPath string `ini:"RuntimeRootPath"` } //LogSection 配置文件 type LogSection struct { SavePath string `ini:"SavePath"` SaveName string `ini:"SaveName"` FileExt string `ini:"FileExt"` TimeFormat string `ini:"TimeFormat"` } //ServerSection 配置文件 type ServerSection struct { RunMode string `ini:"RunMode"` HTTPPort int `ini:"HTTPPort"` ReadTimeout time.Duration `ini:"ReadTimeout"` WriteTimeout time.Duration `ini:"WriteTimeout"` } //MySQLSection 配置文件 type MySQLSection struct { User string `ini:"User"` Password string `ini:"Password"` Host string `ini:"Host"` DBName string `ini:"DBName"` TablePrefix string `ini:"TablePrefix"` } //定义四个导出变量,用于访问数据 var ( App = &AppSection{} Log = &LogSection{} Server = &ServerSection{} MySQL = &MySQLSection{} ) func init() { cfg, err := ini.Load("conf/setting.ini") if err != nil { log.Fatal("Failed to parse 'conf/setting.ini': ", err) } //使用MapTo函数获取参数 err = cfg.Section("app").MapTo(App) if err != nil { log.Fatal("cfg.MapTo AppSection err: ", err) } err = cfg.Section("log").MapTo(Log) if err != nil { log.Fatal("cfg.MapTo LogSection err: ", err) } err = cfg.Section("server").MapTo(Server) if err != nil { log.Fatal("cfg.MapTo ServerSection err: ", err) } Server.ReadTimeout = Server.ReadTimeout * time.Second Server.WriteTimeout = Server.WriteTimeout * time.Second err = cfg.Section("mysql").MapTo(MySQL) if err != nil { log.Fatal("cfg.MapTo MySQLSection err: ", err) } } |
我是不喜欢直接导出变量的,我习惯于导出一个Get函数。
3. 解决因修改导致的错误
当我们修改了setting包之后,它的依赖包也需要修改。
3.1 修改models包 models.go文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
func init() { dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", setting.MySQL.User, setting.MySQL.Password, setting.MySQL.Host, setting.MySQL.DBName) tablePrefix := setting.MySQL.TablePrefix db, err := gorm.Open( mysql.New( mysql.Config{ DriverName: "mysql", //驱动名, "gorm.io/driver/mysql" DSN: dsn, }, ), &gorm.Config{ NamingStrategy: schema.NamingStrategy{ TablePrefix: tablePrefix, //表名前缀 SingularTable: true, //使用单数表名,启用该选项,此时,`User` 的表名应该是 `tablePrefix_user` }, }, ) ... ... |
这个是它的init函数,我们改为从setting中获取配置信息。
3.2 修改logging包 file.go 文件
需要修改两个函数,然后把前面定义的变量删掉了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//getLogFilePath 获取Log文件保存目录 func getLogFilePath() string { return fmt.Sprintf("%s%s", setting.App.RuntimeRootPath, setting.Log.SavePath) } func getLogFileFullPath() string { prefixPath := getLogFilePath() suffixPath := fmt.Sprintf("%s%s.%s", setting.Log.SaveName, time.Now().Format(setting.Log.TimeFormat), setting.Log.FileExt, ) return fmt.Sprintf("%s%s", prefixPath, suffixPath) } |
3.3 修改JWT 中间件 pkg/util/jwt.go 文件
其实就是一个变量需要修改。
1 |
var jwtSecret = []byte(setting.App.JWTSecret) |
3.4 修改分页组件 pkg/util/pagination.go 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package util import ( "ginBlog/pkg/setting" "github.com/gin-gonic/gin" "github.com/unknwon/com" ) //GetPage 获取分页页码 func GetPage(c *gin.Context) int { result := 0 pageSize := setting.App.PageSize page, _ := com.StrTo(c.Query("page")).Int() if page > 0 { result = (page - 1) * pageSize } return result } |
文件不长,就全粘贴上来了。
3.5 修改Routers下router.go文件
1 2 |
//运行环境 Debug or Release gin.SetMode(setting.Server.RunMode) |
运行环境这里需要修改。
3.6 修改Routers/api/v1下 article.go 和 tag.go 文件
两个文件改动点不多,和pagination一样,都是pageSize的问题,就不重复写了。
3.7 修改 main.go 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package main import ( "context" "fmt" "net/http" "os" "os/signal" "time" "ginBlog/pkg/logging" "ginBlog/pkg/setting" "ginBlog/routers" ) func main() { router := routers.InitRouter() s := &http.Server{ Addr: fmt.Sprintf(":%d", setting.Server.HTTPPort), Handler: router, ReadTimeout: setting.Server.ReadTimeout, WriteTimeout: setting.Server.WriteTimeout, MaxHeaderBytes: 1 << 20, } go func() { if err := s.ListenAndServe(); err != nil { logging.Info("Listen: ", err) } }() quit := make(chan os.Signal) signal.Notify(quit, os.Interrupt) <-quit logging.Info("Shutdown Server ...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := s.Shutdown(ctx); err != nil { logging.Fatal("Server Shutdown:", err) } logging.Info("Server exiting") } |
主要的改动点都在 http.Server 结构体初始化那里。
4. 验证功能是否正常
最后我们当然要验证一下,修改是否生效了。
运行 go run main.go 即可。
【Go】gin Blog项目(十) 优化配置结构