go cmd/vet: printf analyzer无法分析匿名函数

pxy2qtax  于 9个月前  发布在  Go
关注(0)|答案(1)|浏览(120)

你使用的Go版本是什么( go version )?

  1. $ go version
  2. go version go1.16 linux/amd64

这个问题在最新版本的发布中是否重现?

是的

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

  1. $ docker run --rm golang:1.16 go env
  2. GO111MODULE=""
  3. GOARCH="amd64"
  4. GOBIN=""
  5. GOCACHE="/root/.cache/go-build"
  6. GOENV="/root/.config/go/env"
  7. GOEXE=""
  8. GOFLAGS=""
  9. GOHOSTARCH="amd64"
  10. GOHOSTOS="linux"
  11. GOINSECURE=""
  12. GOMODCACHE="/go/pkg/mod"
  13. GONOPROXY=""
  14. GONOSUMDB=""
  15. GOOS="linux"
  16. GOPATH="/go"
  17. GOPRIVATE=""
  18. GOPROXY="https://proxy.golang.org,direct"
  19. GOROOT="/usr/local/go"
  20. GOSUMDB="sum.golang.org"
  21. GOTMPDIR=""
  22. GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
  23. GOVCS=""
  24. GOVERSION="go1.16"
  25. GCCGO="gccgo"
  26. AR="ar"
  27. CC="gcc"
  28. CXX="g++"
  29. CGO_ENABLED="1"
  30. GOMOD="/dev/null"
  31. CGO_CFLAGS="-g -O2"
  32. CGO_CPPFLAGS=""
  33. CGO_CXXFLAGS="-g -O2"
  34. CGO_FFLAGS="-g -O2"
  35. CGO_LDFLAGS="-g -O2"
  36. PKG_CONFIG="pkg-config"
  37. GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build813662227=/tmp/go-build -gno-record-gcc-switches"
  38. GOROOT/bin/go version: go version go1.16 linux/amd64
  39. GOROOT/bin/go tool compile -V: compile version go1.16
  40. uname -sr: Linux 4.19.121-linuxkit
  41. /lib/x86_64-linux-gnu/libc.so.6: GNU C Library (Debian GLIBC 2.28-10) stable release version 2.28.

你做了什么?

在包含以下内容的包上运行了 go vet :

  1. package vetexample
  2. import "fmt"
  3. func BuggyCode() error {
  4. failf := func(format string, args ...interface{}) error {
  5. return fmt.Errorf(format, args)
  6. }
  7. return failf("%v")
  8. }

你期望看到什么?

go vetfailf 调用中捕获格式字符串和参数列表之间的不匹配。

你看到了什么?

该包通过了审核。
这种将printf家族函数 Package 在闭包中的模式也可以在Go源代码中找到。
go/src/cmd/go/internal/modfetch/coderepo.go
第324行到第332行的 2f0da6d
| | invalidf:=func(formatstring, args...interface{}) error { |
| | return&module.ModuleError{ |
| | Path: r.modPath, |
| | Err: &module.InvalidVersionError{ |
| | Version: info2.Version, |
| | Err: fmt.Errorf(format, args...), |
| | }, |
| | } |
| | } |
虽然我不太希望 go vet 能够一般地分析一个函数值是否 Package (或是)一个printf家族函数,但它是否可行去分析更有限的情况,即一个作用域为函数的局部变量被赋值为一个函数字面量值?

6tr1vspr

6tr1vspr1#

go vet 具有识别 failf 为 printf Package 器的能力。据我理解,它没有识别它的原因是因为 failf 不是一个顶级函数。也就是说,failf 被认为不是一个 printf Package 器,因为它是一个可以改变内容的变量。
go vet 可以扩展以涵盖本地定义的函数,如 failf,然后在这些 failf(例如,仅在封闭函数中调用,而没有其他地方调用)的情况下检查输入格式问题(例如,作为参数传递或分配值)。
问题是,刚刚描述的代码模式有多普遍?我们是否可以通过某种方式获取数据来证明上述扩展的合理性?

相关问题