之前的问题
之前的代码问题就在于 不支持命令行参数,这会导致 程序的运行比较死板。比如常见的是
我们的可执行文件和 对应的配置文件不在一个目录下的时候 就会出现读不到配置文件的问题
又或者是上述的场景, 虽然 我们的可执行文件和配置文件都在一个目录下
但是我们执行命令的地方 下面并没有配置文件 那也是无法执行的。
所以这套机制 很不灵活。
读取命令行参数
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) > 0 {
for index, arg := range os.Args {
fmt.Printf("args[%d]=%v\n", index, arg)
}
}
}
复制代码
看下程序的执行结果:
很好分辨,其实os的args 就是一个字符串的数组,第一个位置是可执行文件自己,第二个位置开始就是参数了
有了这个基础 再去修改我们的 代码就很容易了
修改框架
首先我们这个初始化文件的地方 增加一个filePath的参数
// Init 加载配置文件
func Init(filePath string) error {
// 如果设置filepath就直接使用 否则用当前目录的
if len(filePath) == 0 {
viper.SetConfigName("config") // 配置文件的名称
viper.SetConfigType("yaml") // 配置文件的扩展名,这里除了json还可以有yaml等格式
// 这个配置可以有多个,主要是告诉viper 去哪个地方找配置文件
// 我们这里就是简单配置下 在当前工作目录下 找配置即可
viper.AddConfigPath(".")
} else {
viper.SetConfigFile(filePath)
}
err := viper.ReadInConfig()
if err != nil {
fmt.Println("viper init failed:", err)
return err
}
// 变化就在这里 有个序列化对象的过程
if err := viper.Unmarshal(Config); err != nil {
fmt.Println("viper Unmarshal err", err)
}
viper.WatchConfig()
viper.OnConfigChange(func(in fsnotify.Event) {
fmt.Println("配置文件已修改")
})
return err
}
复制代码
然后在main函数的开头 读取一下参数即可
func main() {
filePath := ""
if len(os.Args) >= 2 {
filePath = os.Args[1]
}
// 加载配置文件
if err := setting.Init(filePath); err != nil {
fmt.Printf("init settings failed:%s \n", err)
return
}
复制代码
更加标准的支持命令行参数
上述的写法虽然解决了痛点,但是好像不太标准,大部分的时候我们使用别人的程序 都是 -t -p 等等,这里我们也要专业一点 推荐使用flag这个包 来解决我们的问题,代码很简单。
看下main函数的写法
filePath := ""
// 第二个参数 就是命令行的-x 第三个是默认值 第四个是-h的时候的说明
flag.StringVar(&filePath, "file", "", "配置文件地址")
flag.Parse()
// 加载配置文件
if err := setting.Init(filePath); err != nil {
fmt.Printf("init settings failed:%s \n", err)
return
}
// 初始化日志
if err := logger.Init(setting.Config.LogConfig); err != nil {
fmt.Printf("init settings failed:%s \n", err)
return
}
复制代码
然后看下实际的效果:
至此 一个功能基本完备的 web server 开发框架 就结束了。
近期评论