CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

Go标准库flag包的“小陷阱”-源码交易平台丞旭猿

Go语言号称自带电池(battery-included),这意味着Go标准库可开箱即用,为Gopher提供了功能丰富的常用工具包,足以应付多数日常开发所需。尤其在Go语言擅长的领域,Go标准库工具包更是有着广泛的应用。下图是[Go官方2020年用户调查]的结果:

我们看到cli([command-line interface])领域开发占据了Go语言应用的Top2位置,仅次于开发API/RPC服务。而普通cli应用的开发总是离不开标准库的flag包。

flag包估计是很多gopher入门go语言的必经之路。flag使用起来十分简单,功能也不差,常规的命令行程序的flag形式它都支持,比如下面这个示例程序:

// flag_demo1.go package main  import ( 	"flag" 	"fmt" )  var ( 	n = flag.Int("n", 1234, "help message for flag n") )  func main() { 	flag.Parse() 	fmt.Printf("n=%d\n", *n) }

flag_demo1仅支持一个cmd flag: -n。我们可以像下面这样使用flag_demo1这个cli程序,为变量n传值:

$go build flag_demo1.go  $./flag_demo1           n=1234 //默认值  $./flag_demo1 -n 1111 n=1111  $./flag_demo1 --n 1111 n=1111 // --n和-n是等价的  $./flag_demo1 -n=2222  n=2222  $./flag_demo1 --n=2222 n=2222

我们看到,我们可以使用下面四种形式为一个整型flag变量传参数:

  • -n value
  • –n value
  • -n=value
  • –n=value

无论使用哪种形式,它们起到的效果是等价的。

但是当我们将flag放置在cli应用的最后面时,我们要小心了:

$./flag_demo1 show -n=2222 n=1234

我们看到虽然我们在命令行因公flag_demo1的参数列表中进行了-n=2222的参数传递,但flag_demo1的flag包直接无视了这次参数传递,而将变量n置为默认值1234了。

这是因为flag包的命令行参数的解析逻辑是:当碰到第一个非flag参数时,便停止解析。上面命令行执行时传入的show并非flag_demo1的flag参数,因此flag包就会在解析完show后停止后面命令行参数(-n=2222)的解析,于是上述命令行就等价于:

$./flag_demo1 show n=1234

那么n=1234就不足为奇了!这被我称为flag包的第一个小陷阱。不仅像show这样的非flag参数可以阻断flag包对命令行参数列表的继续解析,单独存在的-和–也具有同样的阻断功能:

$./flag_demo1 -- -n=2222   n=1234 $./flag_demo1 - -n=2222  n=1234

我们也常在命令行flag参数中使用bool类的参数值,比如下面示例:

// flag_demo2.go  package main  import ( 	"flag" 	"fmt" )  var ( 	n  = flag.Int("n", 1234, "int value for flag n") 	b1 = flag.Bool("b1", false, "bool value for flag b1") 	b2 = flag.Bool("b2", false, "bool value for flag b2") )  func main() { 	flag.Parse() 	fmt.Printf("n=%d\n", *n) 	fmt.Printf("b1=%t\n", *b1) 	fmt.Printf("b2=%t\n", *b2) }

这个示例中有两个bool型flag参数和一个int型flag参数,我们来运行一下该cli应用:

$go build flag_demo2.go $./flag_demo2 -b1 true -b2 true -n 2222 n=1234 b1=true b2=false

运行的输出似乎与预期结果不符啊!为什么b2变量的值依旧为false,变量n的值为啥不是2222?难道在多个flag参数下,flag包有bug?其实不是的!

问题就在于bool类型flag参数的特殊性。由于一些原因,bool类型flag参数不支持-arg value形式,只支持下面两种形式:

-arg -arg=value

我们按bool类型flag参数的正确传递方法再运行一下上面的flag_demo2:

$./flag_demo2 -b1=true -b2=true -n 2222 n=2222 b1=true b2=true

这回的输出与预期吻合。

但细心的朋友可能会发现,之前的错误用法:

$./flag_demo2 -b1 true -b2 true -n 2222

十分有迷惑性!因为变量b1的输出值是符合预期的,这让人误以为flag参数的传递方法是正确无误的。这种错觉让gopher不知不觉地掉入了**flag包的第二个陷阱**中。而上面的错误flag参数值传递实质上等价于:

$./flag_demo2 -b1

这就是为什么b1=true,而b2和n均为默认值的原因了!

flag包是我们日常最广泛使用的标准库包之一,因此务必了解flag包可能被误用的情况,别掉入flag包的小陷阱中!陷阱虽小,出事是大,希望这里的分享能帮助大家在日常绕过这些陷阱!


相关干货文章推荐:

作者:tonybai

链接:https://www.imooc.com/article/316433

来源:慕课网

本文原创发布于慕课网 ,转载请注明出处,谢谢合作

声明:本文部分素材转载自互联网,如有侵权立即删除 。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容