引言
1 2 3 dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=%s&loc=%s" , "root" ,"123456" ,"localhost" ,"3306" ,"utf8mb4" ,"True" ,"Local" )
上面的行为是非常呆逼的,很生硬,而且一般来说不会吧具体的数值嵌入代码之中,又比如jwt.secretKey,因此就需要使用配置文件
YAML
一款标记性语言,一种较为人性化的数据序列化语言
基本语法
大小写敏感
使用缩进表示层级关系
缩进不允许使用tab,只允许空格
相同成绩的元素左对齐
‘#’表示注释
这个文章中用到引用
1 2 3 4 xxxxxx: xxxxxx: xxxxx xxxxxx: xxxxx xxxxxx: xxxxx
Viper
Viper是Go应用程序的完整配置解决方案
支持:
默认配置
从 JSON, TOML, YAML, HCL 和 Java 属性配置文件读取数据
实时查看和重新读取配置文件(可选)
从环境变量中读取
从远程配置系统(etcd 或 Consul)读取数据并监听变化
从命令行参数读取
从 buffer 中读取
设置显式值
作用:
以 JSON,TOML,YAML,HCL 或 Java 属性格式查找,加载和解组配置文件。
提供一种机制来为不同的配置选项设置默认值。
提供一种机制可以通过命令行标志指定的选项设置来覆盖值。
提供别名系统,轻松重命名参数,而不会破坏现有代码。
当用户提供命令行或配置文件与默认值相同时,可以轻松区分。
反正我知道你看了白看,Viper两个用处
从配置文件上读取数据
输出数据到应用程序
下面的代码实现就是围绕两个方面展开的
实现
为了实现这个配置文件的实现满足通用性,所以这个应用程序不能是简单的为了某个配置而配置的情况,要考虑到如果多个配置的实现。
代码的整体思路还是将yaml格式的数据绑定到结构体全局变量中,然后使用全局变量到对应地点
下载依赖:
1 go get github.com/spf13/viper
结构
1 2 3 4 5 |-configs |-config.yaml |-init.go |-model.go |-setting.go
model.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 package configsimport "github.com/spf13/viper" var ( DbSettings *DatabaseSettings JwtSettings *JWTSettings ) type Setting struct { vp *viper.Viper } type DatabaseSettings struct { Root string Password string Host string Port int Dbname string Charset string ParseTime string Loc string } type JWTSettings struct { Issuer string Subject string SecretKey string }
logic实现
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 func NewSetting () (*Setting,error ){ vp := viper.New() vp.SetConfigName("config" ) vp.SetConfigPath("./configs" ) vp.SetConfigPath("." ) vp.SetConfigType("yaml" ) err := vp.ReadInConfig() if err!=nil { return nil , err } return &Setting{vp} , nil } func (s *Setting) ReadSection(str string , v interface {})error { err := s.vp.Unmashal(str,v) if err!=nil { return err } return nil } func SetUpSettings () error { settings , err := NewSetting() if err!=nil { return err } err1 := settings.ReadSection("填入yaml顶格字段1" ,&DbSettings) if err!=nil { return err } err2 := settings.ReadSection("填入yaml顶格字段2" ,&JwtSettings) if err2!=nil { return err2 } return nil }
init
1 2 3 4 5 6 7 8 func Init () { err := SetUpSettings() if err != nil { log.SugarLogger.Error(err) return } }
使用
数据库中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func Connect () *gorm.DB { dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=%s&loc=%s" , configs.DbSettings.Root, configs.DbSettings.Password, configs.DbSettings.Host, configs.DbSettings.Port, configs.DbSettings.Dbname, configs.DbSettings.Charset, configs.DbSettings.ParseTime, configs.DbSettings.Loc, ) db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { log.SugarLogger.Error(err) return nil } fmt.Println("连接数据库成功" ) return db }
JWT:
1 2 3 4 5 6 7 8 9 10 11 12 tokenString, err := token.SignedString([]byte (configs.JwtSettings.SecretKey)) if err != nil { return "" , err } _, err := jwt.ParseWithClaims(tokenString, claims, func (token *jwt.Token) (interface {}, error ) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil , errors.New("Unexpected Signing Method" ) } return []byte (configs.JwtSettings.SecretKey), nil })
报错(见证一下错误时刻)
1 2 3 4 5 { "level" : "ERROR" , "ts" : "2024-02-03T14:49:33.760+0800" , "caller" : "configs/init.go:8" , "msg" : "Config File \"configs\" Not Found in \"[F:\\\\LearningGo\\\\configs]\"" } { "level" : "ERROR" , "ts" : "2024-02-03T14:51:15.612+0800" , "caller" : "configs/init.go:8" , "msg" : "Config File \"configs\" Not Found in \"[F:\\\\LearningGo\\\\configs\\\\config.yaml]\"" } { "level" : "ERROR" , "ts" : "2024-02-03T14:52:21.998+0800" , "caller" : "configs/init.go:8" , "msg" : "Config File \"configs\" Not Found in \"[F:\\\\LearningGo\\\\config.yaml]\"" } { "level" : "ERROR" , "ts" : "2024-02-03T14:57:52.459+0800" , "caller" : "configs/init.go:8" , "msg" : "Config File \"configs\" Not Found in \"[F:\\\\LearningGo\\\\configs F:\\\\LearningGo]\"" } { "level" : "ERROR" , "ts" : "2024-02-03T14:59:18.138+0800" , "caller" : "configs/init.go:8" , "msg" : "Config File \"config\" Not Found in \"[F:\\\\LearningGo]\"" }
总结
代码通用性而使用封装
配置文件的使用
结构体在数据转化很用有
文献: 编写公共组件 | Go 语言编程之旅 (eddycjy.com)
serendipity/internal/global/jwt/jwt.go at main · hduhelp/serendipity (github.com)
Echin-h/hahaha (github.com)