packagemainimport"fmt"funccustomLogf(str string, args ...interface{}) { fmt.Printf(str, args...)}funcmain() { i :=42customLogf("the answer is %s\n", i)}
$ go tool vet custom-printf-func.go
$ go tool vet -printfuncs customLogf custom-printf-func.go
custom-printf-func.go:11: arg i for printf verb %s of wrong type: int
你可以看到如果没有-printfuncs选项,vet没有任何输出。
3.2 Boolean错误
vet可以检查一直为true、false或者冗余的表达式。
packagemainimport"fmt"funcmain() {var i int// always true fmt.Println(i !=0|| i !=1) // always false fmt.Println(i ==0&& i ==1) // redundant check fmt.Println(i ==0&& i ==0)}
$ go vet bool-expr.go
bool-expr.go:9: suspect or: i != 0 || i != 1
bool-expr.go:12: suspect and: i == 0 && i == 1
bool-expr.go:15: redundant and: i == 0 && i == 0
这种类型的警告常常是非常危险的,可以引起讨厌的bug。大多数情况下是由于排版错误引起的。
3.3 Range循环
当读取变量的时候,在range块内的go协程可能是有问题的。在这些场景下,vet可以检测到它们:
packagemainimport"fmt"funcmain() { words := []string{"foo", "bar", "baz"}for _, word :=range words {gofunc() { fmt.Println(word) }() }}
$ go tool vet range.go
range.go:10: range variable word captured by func literal
3.4 Unreachable的代码
下面的例子包含3个函数,带有不能到达的代码,每个函数使用了不同的方式。
packagemainimport"fmt"funcadd(a int, b int) int {return a + b fmt.Println("unreachable")return0}funcdiv(a int, b int) int {if b ==0 {panic("division by 0") } else {return a / b } fmt.Println("unreachable")return0}funcfibonnaci(n int) int {switch n {case0: return1case1: return1default: returnfibonnaci(n-1) +fibonnaci(n-2) } fmt.Println("unreachable")return0}funcmain() { fmt.Println(add(1, 2)) fmt.Println(div(10, 2)) fmt.Println(fibonnaci(5))}
$ go vet unreachable.go
unreachable.go:8: unreachable code
unreachable.go:19: unreachable code
unreachable.go:33: unreachable code
3.5 混杂的错误
这里是一个代码段,包含了其他的几个vet可以检测的混杂的错误:
packagemainimport ("fmt""log""net/http")funcf() {}funcmain() { // Self assignment i :=42 i = i // a declared function cannot be nil fmt.Println(f ==nil) // shift too long fmt.Println(i >>32) // res used before checking err res, err := http.Get("https://www.spreadsheetdb.io/")defer res.Body.Close()if err !=nil { log.Fatal(err) }}
$ go tool vet misc.go
misc.go:14: self-assignment of i to i
misc.go:17: comparison of function f == nil is always false
misc.go:20: i might be too small for shift of 32
misc.go:24: using res before checking for errors
3.6 误报和漏报
有时,vet可能忽略了错误,并警告可疑代码,这些代码实际上是正确的。下面的例子:
packagemainimport"fmt"funcmain() { rate :=42// this condition can never be trueif rate >60&& rate <40 { fmt.Println("rate %:", rate) }}
$ go tool vet false.go
false.go:10: possible formatting directive in Println call