大家好,我是 Go 学堂的渔夫子。今天给大家介绍一个在项目中如何将命令行参数组织到文件中并进行解析的案例
golang标准库提供了flag包来处理命令行参数。常规的使用都是在命令行中启动服务的时候一一的输入,让程序解析。今天给大家介绍一种可以从文件中读取命令行参数的实现方法。
01 flag的常规应用下面我们通过代码来演示下flag的常规应用。如下代码:
var(RedisAddressstring)funcinit(){flag.StrVar(&RedisAddress,"redis_address","127.0.0.1","this is redis address")}funcmain(){flag.Parse()ifRedisAddress!=""{//redis初始化操作}fmt.Printf("redis address:%s\n",RedisAddress)}
然后在命令行中进行编译或直接运行时要指定-redis_address参数,如下:
gorunmain.go-redis_address=redisaddr.goxuetang.com
随着项目规模的增大,需要的命令行参数越来越多,假设有50个命令行参数甚至更多,如果我们一个一个指定的话,可想而知会是一件多么可怕的事情:参数多,难以维护,容易出错。下面我们就介绍通过让程序从配置文件中读取的方法。
02 通过文件读取命令行参数的flag应用
常规应用中,我们看到,读取并解析命令行参数的逻辑主要在flag.Parse中。我们对flag.Parse()进一步查看,看到源码包中flag.Parse()函数实际上是调用了CommandLine.Parse(arguments []string) error函数,如下:
funcParse(){// Ignore errors; CommandLine is set for ExitOnError.CommandLine.Parse(os.Args[1:])}
通过上面代码可知,os.Args[1:]就是命令行后跟的所有参数的集合(在上面的例子中就是 [-redis_address=http://redis-test.goxuetang.com]),然后CommandLine.Parse对该字符串集合进行实际的解析。
那我们要实现的目标实际上就是将文件中的每一行读取出来,组织成CommandLine.Parse函数可接收的参数即可。如下图所示flag常规解析和读取文件方式的示意图:
好了,思路讲清楚后,我们来看下代码实现
03 代码实现
我们将实现的函数封装在flagx的包中,本文意图是讲解实现的思路,所以在代码中忽略了错误处理,大家在实际项目中自行添加即可。
packageflagx//存储命令行传过来的文件路径varFlagFilestringfuncinit(){//注册命令行的flagfile参数flag.Var(&FlagFile,"flagfile","")}//在Parse函数中调用,将解析到的命令行参数打印出来funcvisitFlag(f*flag.Flag){fmt.Println(f.Name+"="+f.Value.String())}funcParse()error{//先解析命令行中的-flagfile参数flag.Parse()varvalidFlagLines[]stringflagContents,_:=ioutil.ReadFile(FlagFile)configContent:=string(flagContents)// 统一使用\n作为换行符,以便后面按分隔符分隔字符串成切片configContent=strings.Replace(configContent,"\r\n","\n",10000)flagLines:=strings.Split(configContent,"\n")for_,line:=rangeflagLines{//忽略掉以 开头的注释行iflen([]rune(line))!=0&&string([]rune(line)[0])!=""{//将每一行作为一个有效的命令行参数validFlagLines=append(validFlagLines,line)}}//实际执行解析命令行参数的地方,这里就又和常规的flag调用一样了_:=flag.CommandLine.Parse(validFlagLines)//主动在命令行设置的参数具有更高的优先级,会覆盖掉配置文件中相同的命令行参数flag.Parse()flag.VisitAll(visitFlag)returnnil}
假设命令行参数文件存在于文件/data/conf/prod.gflags中,内容如下:
redis地址-redis_address=redisaddr.goxuetang.comredis端口-redis_port=9999其他所有的命令行参数
好,写个main函数测试一下,main函数中引入的http://gotech.github.com/m/flagfile/flagx包是我项目下的定义路径,大家在实际开发中根据自己的项目组织包路径即可。
packagemainimport("flag""fmt""gotech.github.com/m/flagfile/flagx")var(RedisAddressstringRedisPortint)funcinit(){flag.StringVar(&RedisAddress,"redis_address","127.0.0.1","this is redis address")flag.IntVar(&RedisPort,"redis_port",6379,"this is redis port")}funcmain(){//这里调用我们自定实现的Parse函数err:=flagx.Parse()fmt.Println("err:",err)ifRedisAddress!=""&&RedisPort!=0{//redis初始化操作}fmt.Printf("redis address:%s,port:%d\n",RedisAddress,RedisPort)}
执行如下命令
gorunmain.go-flagfile=/data/conf/prod.gflags
04 总结
和常规的flag应用相比,将命令行参数写在配置文件中,可以提高命令行参数的可读性以及可维护性。该方法的实现思路主要是应用了flag.Parse解析命令行参数底层的CommandLine.Parse(arguments []string)的函数功能,将文件中的每行命令行参数组织成一个切片,然后调用CommandLine.Parse方法。
声明:本文部分素材转载自互联网,如有侵权立即删除 。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容