go tool vet是你的好朋友,不要忽视它。
vet是一个优雅的工具,每个Go开发者都要知道并会使用它。它会做代码静态检查发现可能的bug或者可疑的构造。vet是Go tool套件的一部分,我们会在以后的文章中详细描述tool套件。它和go编译器一起发布,这意味着它不需要额外的依赖,可以很方便地通过以下的命令调用:
$ go tool vet <directory|files>
本文中所有的go代码段可以正常编译。这使得go vet有价值:它可以在编译阶段和运行阶段发现bug。
同时也注意,本文中的大多数代码都是故意写的很难看,不要使用。
在go vet和go tool vet之间选择
go vet
和go tool vet
实际上是两个分开的命令。
go vet,只在一个单独的包内可用,不能使用flag 选项(来激活某些指定的检测)。
go tool vet更加完整,它可用用于文件和目录。目录被递归遍历来找到包。go tool vet也可以按照检测的分组激活选项。
你可以打开一个终端,并比较go vet --help 和go tool vet --help两个命令的不同。
Print-format 错误
尽管go是强类型的,但是printf-format错误不会在编译阶段检测。C开发者可能使用默认激活的gcc的-Wformat选项。如果参数不能匹配格式它可以给出一个很好的警告:
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
不幸的是,在Go里面编译器没有任何输出。这是vet发挥作用的时候了。考虑下面的例子:
package mainimport "fmt" func main() { str := "hello world!" fmt.Printf("%d\n", str) }
这是一个典型的错误,一个坏的printf 格式。因为str是一个字符串,所以format应该用%s
,而不是%d
。
这个代码编译后运行,打印出%!d(string=hello world!)
,不够友好。你可以点击源码下面的“run”链接来自己检查。现在,我们开始运行vet。
$ go tool vet ex1.go
ex1.go:7: arg str for printf verb %d of wrong type: string
当一个指针被使用时,vet也可以检测:
package main import "fmt" func main() { str := "hello world!" fmt.Printf("%s\n", &str) }