go语言中的第三方包viper真的是无比强大
最近有个小项目,是go语言编写的,需要读取配置文件,就使用了viper包,之前了解到这货是无比的强大。开始看文档,写代码。下面是几行关键代码
func initConfig() {
viper.SetConfigName("config")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s", err))
}
}
编译很快通过,但是运行的时候却报错了
⇒ ./appconfig
panic: Fatal error config file: Config File "config" Not Found in "[/Users/zz/workspace/appconfig/bin]"
goroutine 1 [running]:
main.initConfig()
/Users/zz/workspace/appconfig/src/services/appconfig/appconfig.go:38 +0x29b
main.main()
/Users/zz/workspace/appconfig/src/services/appconfig/appconfig.go:44 +0x2b
但是我确定有config这个文件啊,并且目录也没错啊,这是怎么回事呢? 配置文件支持json格式,并且后缀是不需要写,这也是官网文档上写着的呀。再来看看文档
下面是github上viper关于读取配置文件的文档
Viper requires minimal configuration so it knows where to look for config files. Viper supports JSON, TOML, YAML, HCL, and Java Properties files. Viper can search multiple paths, but currently a single Viper instance only supports a single configuration file. Viper does not default to any configuration search paths leaving defaults decision to an application.
Here is an example of how to use Viper to search for and read a configuration file. None of the specific paths are required, but at least one path should be provided where a configuration file is expected.
viper.SetConfigName("config") // name of config file (without extension)
viper.AddConfigPath("/etc/appname/") // path to look for the config file in
viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths
viper.AddConfigPath(".") // optionally look for config in the working directory
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
代码中的配置文件确实不需要写后追命,但是没说文件系统中的文件也可以不写后缀,尝试把配置文件名改为config.json,马上就OK了。
看一下viper源码来验证一下
var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"}
func (v *Viper) searchInPath(in string) (filename string) {
jww.DEBUG.Println("Searching for config in ", in)
for _, ext := range SupportedExts {
jww.DEBUG.Println("Checking for", filepath.Join(in, v.configName+"."+ext))
if b, _ := exists(v.fs, filepath.Join(in, v.configName+"."+ext)); b {
jww.DEBUG.Println("Found: ", filepath.Join(in, v.configName+"."+ext))
return filepath.Join(in, v.configName+"."+ext)
}
}
return ""
}
从上面的源码可以看出,viper会按照既定的后缀列表来查找配置文件,找到任意一个,立即返回。这里有两个问题需要说明一下,一是viper单个实例只支持一个配置文件,二是有配置文件名相同,后缀不同的话,优先使用json格式,其次是toml。