Go Vet

go vet用于检查代码中的错误,例如printf的参数错误等。

一、用法

go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]

一般使用

go vet /path/to/file

二、Goland集成

可以使用Tools->Go Tools->Go Vet File

三、简介

3.1 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!),不够友好。现在,我们开始运行vet。

当一个指针被使用时,vet也可以检测:

vet也可以找到所有的Printf()家族函数(Printf(), Sprintf(), Fprintf(), Errorf(), Fatalf(), Logf(), Panicf()等)格式错误。但是如果你要实现一个函数,接收和printf类似的参数,你可以使用-printfuncs选项使得vet来检测。

你可以看到如果没有-printfuncs选项,vet没有任何输出。

3.2 Boolean错误

vet可以检查一直为truefalse或者冗余的表达式。

这种类型的警告常常是非常危险的,可以引起讨厌的bug。大多数情况下是由于排版错误引起的。

3.3 Range循环

当读取变量的时候,在range块内的go协程可能是有问题的。在这些场景下,vet可以检测到它们:

注意,这个代码包含竞态,可能不输出任何东西。事实上,main函数可能在所有的协程执行前已经结束,这导致进程退出。

3.4 Unreachable的代码

下面的例子包含3个函数,带有不能到达的代码,每个函数使用了不同的方式。

3.5 混杂的错误

这里是一个代码段,包含了其他的几个vet可以检测的混杂的错误:

3.6 误报和漏报

有时,vet可能忽略了错误,并警告可疑代码,这些代码实际上是正确的。下面的例子:

这种情况很明显永远都不是true,但是并不会检测出来。然而,vet警告了一种可能的错误(使用Println()而不是Printf()),这里的Println()非常好用。

总的来说,使用go tool vet提示很少会有误报与漏报的情况。

3.7 性能

vet的README描述了,只是可能的错误是值得检测的。这种方式保证了vet不会变慢。

此时,Docker包含了23M的Go代码(包含依赖)。在Core i5机器上,vet花费了21.6秒来分析它,这是1MB/s的数量级。

Last updated

Was this helpful?