go ``` cmd/vet: make printf检查在参数更改时更加精确 ```

dgsult0t  于 6个月前  发布在  Go
关注(0)|答案(3)|浏览(44)

对于 #26486https://golang.org/cl/125039,将 printf 检查更改为仅警告那些在将参数传递给 fmt.Printf(或其他函数)之前不修改这些参数的函数。该问题中的例子,取自实际代码,如下:

func dbg(s string, va ...interface{}) {
	if s == "" {
		s = strings.Repeat("%v ", len(va))
	}
	_, fn, fl, _ := runtime.Caller(1)
	fmt.Printf("dbg %s:%d: ", path.Base(fn), fl)
	fmt.Printf(s, va...)
	fmt.Println()
}

这可以作为 dbg("", err) 调用。CL 125039 中的修复意味着我们不再对此类函数发出 printf 警告:

func Prefix(s string, args ...interface{}) {
    s = "error: " + s
    fmt.Printf(s, args)
}

我们应该找到一种方法,在继续发出 Prefix 的警告的同时,不对 dbg 发出警告。

t98cgbkg

t98cgbkg1#

https://golang.org/cl/125039提到了这个问题:cmd/vet: if a function modifies its args, it's not a print wrapper

0ve6wy6x

0ve6wy6x2#

在我看来,这需要在vet中使用更高级的开发工具,例如使用x/tools/go/ssa

wsewodh2

wsewodh23#

我已经看到了an issue,使用以下代码,现在在v1.11中无法通过验证:

func Say(expected string, args ...interface{}) *sayMatcher {
	formattedRegexp := expected
	if len(args) > 0 {
		formattedRegexp = fmt.Sprintf(expected, args...)
	}
	return &sayMatcher{
		re: regexp.MustCompile(formattedRegexp),
	}
}

像这样重写可以让它通过验证,但这似乎是一个非常脆弱的“修复”。

func Say(expected string, args ...interface{}) *sayMatcher {
	if len(args) > 0 {
		expected = fmt.Sprintf(expected, args...)
	}
	return &sayMatcher{
		re: regexp.MustCompile(expected),
	}
}

理想情况下,go vet应该能够判断并非所有分支都是打印 Package 器,并忽略此类函数。

相关问题