在项目开发中,配置文件的合理的获取和更新是一个基本的功能。项目上线后修改配置项,修改配置以后若是还从新启动项目才能生效,这样效果并很差。为了可以在不影响项目正常运行的状况下修改配置项,就须要用到配置热更新。例如:上线后想要修改日志的级别,能够直接修改配置文件,项目自动扫描配置文件,若是发现文件被修改,则从新获取配置信息。读取配置和配置热更新有两种方式:mysql
package main import ( "file-store/handler" "file-store/models" "file-store/utils" "fmt" "log" "net/http" "github.com/fsnotify/fsnotify" ) func main() { configPath := "/Users/apple/workplace/file-store/config/config.yaml" configDir := "/Users/apple/workplace/file-store/config" // 加载配置文件 _ = utils.InitConfig(configPath, "config") fmt.Printf("配置为:%s\n", utils.Conf.Token.Salt) watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal(err) } defer watcher.Close() done := make(chan bool) go func() { for { select { case event := <-watcher.Events: if event.Op&fsnotify.Write == fsnotify.Write { _ = utils.InitConfig(configPath, "config") fmt.Printf("更新配置为:%s\n", utils.Conf.Token.Salt) } case err := <-watcher.Errors: log.Println("error:", err) } } }() fmt.Printf("数据库配置为:%s, %s\n", utils.Conf.Mysql.Drive, utils.Conf.Mysql.Address) // 数据库操做 models.MysqlInit(utils.Conf.Mysql.Drive, utils.Conf.Mysql.Address) // 监听端口 err = http.ListenAndServe("127.0.0.1:8000", nil) if err != nil { fmt.Printf("Failed to start server, err %s", err.Error()) } // 监控文件 err = watcher.Add(configPath) if err != nil { log.Fatal(err) } // 监控文件夹 err = watcher.Add(configDir) if err != nil { log.Fatal(err) } <-done }
package utils import ( "fmt" "io/ioutil" "sync" "gopkg.in/yaml.v2" ) type Config struct { File *File `yaml:"file"` Mysql *Mysql `yaml:"mysql"` Token *Token `yaml:"token"` } type File struct { Path string `yaml:"path"` } type Mysql struct { Drive string `yaml:"drive"` Address string `yaml:"address"` } type Token struct { Salt string `yaml:"salt"` Issue string `yaml:"issue"` } var Conf *Config // InitConfig 读取yaml配置文件 func InitConfig(configPath, configName string) error { var locker = new(sync.RWMutex) yamlFile, err := ioutil.ReadFile(configPath) if err != nil { panic(err) } locker.Lock() err1 := yaml.Unmarshal(yamlFile, &Conf) if err1 != nil { panic(err) } locker.Unlock() fmt.Println(Conf.Token.Salt) return nil }
package utils import ( "fmt" "github.com/spf13/viper" ) type Config struct { File *File `yaml:"file"` Mysql *Mysql `yaml:"mysql"` Token *Token `yaml:"token"` } type File struct { Path string `yaml:"path"` } type Mysql struct { Drive string `yaml:"drive"` Address string `yaml:"address"` } type Token struct { Salt string `yaml:"salt"` Issue string `yaml:"issue"` } // 全局配置 var config = new(Config) // InitConfig 读取yaml配置文件 func InitConfig(configPath, configName, configType string) error { viper.SetConfigName(configName) // 配置文件名 viper.SetConfigType(configType) // 配置文件类型,例如:toml、yaml等 viper.AddConfigPath(configPath) // 查找配置文件所在的路径,屡次调用能够添加多个配置文件搜索的目录 // 读取配置文件配置,并处理错误 if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { return err } } // 监控配置文件变化 viper.WatchConfig() viper.Unmarshal(config) if err := validateConfig(config); err != nil { return err } return nil } // 获取全局配置 func GetConfig() *Config { return config } // validateConfig:校验配置信息 func validateConfig(conf *Config) error { var ( file = conf.File.Path drive = conf.Mysql.Drive address = conf.Mysql.Address salt = conf.Token.Salt issue = conf.Token.Issue ) if file == "" { return fmt.Errorf("invalid file path: %s\n", file) } if drive == "" { return fmt.Errorf("invalid drive: %s\n", drive) } if address == "" { return fmt.Errorf("invalid address: %s\n", address) } if salt == "" { return fmt.Errorf("invalid salt: %s\n", salt) } if issue == "" { return fmt.Errorf("invalid issue: %s\n", issue) } return nil }
package main import ( "file-store/handler" "file-store/models" "file-store/utils" "fmt" "net/http" ) func main() { configPath := "/Users/apple/workplace/file-store/config" // 配置初始化 err := utils.InitConfig(configPath, "config", "yaml") if err != nil { fmt.Printf("Failed to init config, err is %s\n", err) } // 获取全局配置 conf := utils.GetConfig() fmt.Println(conf.File.Path) // 数据库操做 models.MysqlInit(conf.Mysql.Drive, conf.Mysql.Address) // 监听端口 err = http.ListenAndServe("127.0.0.1:8000", nil) if err != nil { fmt.Printf("Failed to start server, err %s", err.Error()) } }