当前位置: 首页 > news >正文

wordpress网站不稳定太平洋网站建设

wordpress网站不稳定,太平洋网站建设,自己怎样免费建网站,400套商业网站的静态模板go vet 是 Go 语言自带的一个工具#xff0c;用于分析 Go 代码中的常见错误和潜在问题。它可以检查代码中可能存在的各种问题#xff0c;例如#xff1a; 未使用的变量、函数或包 可疑的函数调用 错误的函数签名 程序中的竞态条件 错误的类型转换等 本文意图指令当前go vet所… go vet 是 Go 语言自带的一个工具用于分析 Go 代码中的常见错误和潜在问题。它可以检查代码中可能存在的各种问题例如 未使用的变量、函数或包 可疑的函数调用 错误的函数签名 程序中的竞态条件 错误的类型转换等 本文意图指令当前go vet所有的检测项及其作用 目前集成进go vet的只有30个,很多可能因为噪音太多而没有集成进去 Run go help vet for details. Run go tool vet help for a full list of flags and analyzers. Run go tool vet -help for an overview. go tool vet help vet is a tool for static analysis of Go programs.vet examines Go source code and reports suspicious constructs,such as Printf calls whose arguments do not align with the formatstring. It uses heuristics that do not guarantee all reports aregenuine problems, but it can find errors not caught by the compilers.Registered analyzers:    asmdecl      report mismatches between assembly files and Go declarations    assign       check for useless assignments    atomic       check for common mistakes using the sync/atomic package    bools        check for common mistakes involving boolean operators    buildtag     check //go:build and // build directives    cgocall      detect some violations of the cgo pointer passing rules    composites   check for unkeyed composite literals    copylocks    check for locks erroneously passed by value    directive    check Go toolchain directives such as //go:debug    errorsas     report passing non-pointer or non-error values to errors.As    framepointer report assembly that clobbers the frame pointer before saving it    httpresponse check for mistakes using HTTP responses    ifaceassert  detect impossible interface-to-interface type assertions    loopclosure  check references to loop variables from within nested functions    lostcancel   check cancel func returned by context.WithCancel is called    nilfunc      check for useless comparisons between functions and nil    printf       check consistency of Printf format strings and arguments    shift        check for shifts that equal or exceed the width of the integer    sigchanyzer  check for unbuffered channel of os.Signal    slog         check for invalid structured logging calls    stdmethods   check signature of methods of well-known interfaces    stringintconv check for string(int) conversions    structtag    check that struct field tags conform to reflect.StructTag.Get    testinggoroutine report calls to (*testing.T).Fatal from goroutines started by a test.    tests        check for common mistaken usages of tests and examples    timeformat   check for calls of (time.Time).Format or time.Parse with 2006-02-01    unmarshal    report passing non-pointer or non-interface values to unmarshal    unreachable  check for unreachable code    unsafeptr    check for invalid conversions of uintptr to unsafe.Pointer    unusedresult check for unused results of calls to some functionsBy default all analyzers are run.To select specific analyzers, use the -NAME flag for each one, or -NAMEfalse to run all analyzers not explicitly disabled.Core flags:  -V    print version and exit  -all        no effect (deprecated)  -asmdecl        enable asmdecl analysis  -assign        enable assign analysis  -atomic        enable atomic analysis  -bool        deprecated alias for -bools  -bools        enable bools analysis  -buildtag        enable buildtag analysis  -buildtags        deprecated alias for -buildtag  -c int        display offending line with this many lines of context (default -1)  -cgocall        enable cgocall analysis  -composites        enable composites analysis  -compositewhitelist        deprecated alias for -composites.whitelist (default true)  -copylocks        enable copylocks analysis  -directive        enable directive analysis  -errorsas        enable errorsas analysis  -flags        print analyzer flags in JSON  -framepointer        enable framepointer analysis  -httpresponse        enable httpresponse analysis  -ifaceassert        enable ifaceassert analysis  -json        emit JSON output  -loopclosure        enable loopclosure analysis  -lostcancel        enable lostcancel analysis  -methods        deprecated alias for -stdmethods  -nilfunc        enable nilfunc analysis  -printf        enable printf analysis  -printfuncs value        deprecated alias for -printf.funcs (default (*log.Logger).Fatal,(*log.Logger).Fatalf,(*log.Logger).Fatalln,(*log.Logger).Panic,(*log.Logger).Panicf,(*log.Logger).Panicln,(*log.Logger).Print,(*log.Logger).Printf,(*log.Logger).Println,(*testing.common).Error,(*testing.common).Errorf,(*testing.common).Fatal,(*testing.common).Fatalf,(*testing.common).Log,(*testing.common).Logf,(*testing.common).Skip,(*testing.common).Skipf,(testing.TB).Error,(testing.TB).Errorf,(testing.TB).Fatal,(testing.TB).Fatalf,(testing.TB).Log,(testing.TB).Logf,(testing.TB).Skip,(testing.TB).Skipf,fmt.Append,fmt.Appendf,fmt.Appendln,fmt.Errorf,fmt.Fprint,fmt.Fprintf,fmt.Fprintln,fmt.Print,fmt.Printf,fmt.Println,fmt.Sprint,fmt.Sprintf,fmt.Sprintln,log.Fatal,log.Fatalf,log.Fatalln,log.Panic,log.Panicf,log.Panicln,log.Print,log.Printf,log.Println,runtime/trace.Logf)  -rangeloops        deprecated alias for -loopclosure  -shift        enable shift analysis  -sigchanyzer        enable sigchanyzer analysis  -slog        enable slog analysis  -source        no effect (deprecated)  -stdmethods        enable stdmethods analysis  -stringintconv        enable stringintconv analysis  -structtag        enable structtag analysis  -tags string        no effect (deprecated)  -testinggoroutine        enable testinggoroutine analysis  -tests        enable tests analysis  -timeformat        enable timeformat analysis  -unmarshal        enable unmarshal analysis  -unreachable        enable unreachable analysis  -unsafeptr        enable unsafeptr analysis  -unusedfuncs value        deprecated alias for -unusedresult.funcs (default context.WithCancel,context.WithDeadline,context.WithTimeout,context.WithValue,errors.New,fmt.Errorf,fmt.Sprint,fmt.Sprintf,sort.Reverse)  -unusedresult        enable unusedresult analysis  -unusedstringmethods value        deprecated alias for -unusedresult.stringmethods (default Error,String)  -v    no effect (deprecated)To see details and flags of a specific analyzer, run vet help name. vet 是一个用于对 Go 程序进行静态分析的工具。vet 检查 Go 源代码并报告可疑的结构例如 Printf 调用的参数与格式字符串不对齐。它使用的启发式方法不能保证所有报告都是真正的问题但它可以发现编译器没有捕获的错误。已注册的分析器- asmdecl报告汇编文件和 Go 声明之间的不匹配- assign检查无用的赋值- atomic检查使用 sync/atomic 包的常见错误- bools检查涉及布尔运算符的常见错误- buildtag检查 //go:build 和 // build 指令- cgocall检测一些违反 cgo 指针传递规则的情况- composites检查未键控的复合文字- copylocks检查错误地通过值传递的锁- directive检查 Go 工具链指令如 //go:debug- errorsas报告将非指针或非错误值传递给 errors.As 的情况- framepointer报告在保存帧指针之前破坏帧指针的汇编- httpresponse检查使用 HTTP 响应时的错误- ifaceassert检测不可能的接口到接口类型断言- loopclosure检查在嵌套函数内部引用循环变量的情况- lostcancel检查是否调用了由 context.WithCancel 返回的 cancel 函数- nilfunc检查函数与 nil 的无用比较- printf检查 Printf 格式字符串和参数的一致性- shift检查移位是否等于或超过整数的宽度- sigchanyzer检查未缓冲的 os.Signal 通道- slog检查无效的结构化日志调用- stdmethods检查众所周知接口的方法签名- stringintconv检查 string(int) 转换- structtag检查结构体字段标记是否符合 reflect.StructTag.Get- testinggoroutine报告从测试启动的 goroutine 中调用 (*testing.T).Fatal。- tests检查测试和示例的常见错误用法- timeformat检查调用 (time.Time).Format 或 time.Parse 是否使用 2006-02-01- unmarshal报告将非指针或非接口值传递给 unmarshal 的情况- unreachable检查无法到达的代码- unsafeptr检查将 uintptr 转换为 unsafe.Pointer 的无效转换- unusedresult检查某些函数调用的未使用结果默认情况下所有分析器都会运行。要选择特定的分析器请为每个分析器使用 -NAME 标志或者使用 -NAMEfalse 运行未明确禁用的所有分析器。核心标志- -V打印版本并退出- -all无效已弃用- -asmdecl启用 asmdecl 分析- -assign启用 assign 分析- -atomic启用 atomic 分析- -bool-bools 的已弃用别名- -bools启用 bools 分析- -buildtag启用 buildtag 分析- -buildtags-buildtag 的已弃用别名- -c int以这么多行的上下文显示有问题的代码行默认值为 -1- -cgocall启用 cgocall 分析- -composites启用 composites 分析- -compositewhitelist-composites.whitelist 的已弃用别名默认值为 true- -copylocks启用 copylocks 分析- -directive启用 directive 分析- -errorsas启用 errorsas 分析- -flags以 JSON 格式输出分析器标志- -framepointer启用 framepointer 分析- -httpresponse启用 httpresponse 分析- -ifaceassert启用 ifaceassert 分析- -json发出 JSON 输出- -loopclosure启用 loopclosure 分析- -lostcancel启用 lostcancel 分析- -methods-stdmethods 的已弃用别名- -nilfunc启用 nilfunc 分析- -printf启用 printf 分析- -printfuncs value-printf.funcs 的已弃用别名默认值为 (*log.Logger).Fatal,(*log.Logger).Fatalf,(*log.Logger).Fatalln,(*log.Logger).Panic,(*log.Logger).Panicf,(*log.Logger).Panicln,(*log.Logger).Print,(*log.Logger).Printf,(*log.Logger).Println,(*testing.common).Error,(*testing.common).Errorf,(*testing.common).Fatal,(*testing.common).Fatalf,(*testing.common).Log,(*testing.common).Logf,(*testing.common).Skip,(*testing.common).Skipf,(testing.TB).Error,(testing.TB).Errorf,(testing.TB).Fatal,(testing.TB).Fatalf,(testing.TB).Log,(testing.TB).Logf,(testing.TB).Skip,(testing.TB).Skipf,fmt.Append,fmt.Appendf,fmt.Appendln,fmt.Errorf,fmt.Fprint,fmt.Fprintf,fmt.Fprintln,fmt.Print,fmt.Printf,fmt.Println,fmt.Sprint,fmt.Sprintf,fmt.Sprintln,log.Fatal,log.Fatalf,log.Fatalln,log.Panic,log.Panicf,log.Panicln,log.Print,log.Printf,log.Println,runtime/trace.Logf- -rangeloops-loopclosure 的已弃用别名- -shift启用 shift 分析- -sigchanyzer启用 sigchanyzer 分析- -slog启用 slog 分析- -source无效已弃用- -stdmethods启用 stdmethods 分析- -stringintconv启用 stringintconv 分析- -structtag启用 structtag 分析- -tags string无效已弃用- -testinggoroutine启用 testinggoroutine 分析- -tests启用 tests 分析- -timeformat启用 timeformat 分析- -unmarshal启用 unmarshal 分析- -unreachable启用 unreachable 分析- -unsafeptr启用 unsafeptr 分析- -unusedfuncs value-unusedresult.funcs 的已弃用别名默认值为 context.WithCancel,context.WithDeadline,context.WithTimeout,context.WithValue,errors.New,fmt.Errorf,fmt.Sprint,fmt.Sprintf,sort.Reverse- -unusedresult启用 unusedresult 分析- -unusedstringmethods value-unusedresult.stringmethods 的已弃用别名默认值为 Error,String- -v无效已弃用要查看特定分析器的详细信息和标志请运行 vet help name。 文中完整代码见 https://github.com/cuishuang/govet-demo 相关使用何时会抛出提示可以参考相应的testdata中的a.go文件 1. asmdecl[1] report mismatches between assembly files and Go declarations asmdecl 的全称是 assembly declaration主要用于检查 Go 代码中与汇编声明相关的错误例如在汇编代码中使用了无效的符号或者在汇编代码中使用了错误的语法等。它有助于确保 Go 代码中的汇编部分正确地与 Go 代码进行交互以避免由于汇编代码问题导致的潜在错误。 2. assign check for useless assignments 该检查器报告 x x 或 a[i] a[i] 形式的分配。 这些几乎总是无用的即使没有用它们通常也是一个错误。 assign 是 go vet 中的一个检查项主要用于检查可能出现的变量赋值问题。 具体来说assign 检查的是在变量赋值时可能出现的问题比如 将变量赋值给自身例如 x x 在多重赋值中左边的变量数量和右边的值数量不一致 将一个值赋给一个不兼容的变量类型例如将一个字符串赋给一个整型变量 在 if、 for、 switch 等语句中将一个值赋给一个布尔型变量而不是比较表达式 在赋值语句中使用了未定义的变量。 以下是一些示例代码展示了 assign 可能会检查出的问题 package mainfunc main() {    x : 1    x  x  // 将变量赋值给自身    y, z : 1, 2    y, z, _  1, 2  // 左边的变量数量和右边的值数量不一致    var a int    a  hello  // 将一个字符串赋给一个整型变量    b : true    b  1  // 在 if、for、switch 等语句中将一个值赋给一个布尔型变量而不是比较表达式    c  1  // 使用了未定义的变量} 使用 go vet 命令检查上述代码时会输出以下警告信息(这些信息不会一次性全部输出但凡有一个满足就会抛出) # command-line-arguments./main.go:5:5: self-assignment of x./main.go:7:9: assignment mismatch: 2 variables but 3 values./main.go:9:5: cannot use hello (type string) as type int in assignment./main.go:11:5: b is bool, suggest b  1 instead./main.go:13:5: undefined: c 相关代码: https://github.com/golang/tools/blob/master/go/analysis/passes/assign/assign.go#L64 3. atomic check for common mistakes using the sync/atomic package atomic 是 Go 语言自带的一种原子操作库用于实现在多个 goroutine 中安全地读写共享变量。go vet 中的 atomic 检查项主要用于检查在使用原子操作时可能出现的一些问题。 package mainimport ( sync/atomic)func main() { var x int64 x  atomic.AddInt64(x, 1) //  direct assignment to atomic value} 使用 go vet 命令检查上述代码时会输出以下警告信息 # command-line-arguments./main.go:9:2: direct assignment to atomic value 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/atomic/testdata/src/a/a.go 链接代码展示了 go vet 中的 atomic 检查项可能会检查到的几种直接赋值给原子变量的情况。这些情况可能会导致并发问题因此需要使用原子操作来确保多个 goroutine 安全地访问共享变量。 具体来说这段代码分别展示了以下几种情况 直接赋值给原子变量 x atomic.AddUint64(x, 1) 左侧包含其他变量的赋值语句 _, x 10, atomic.AddUint64(x, 1) 和 x, _ atomic.AddUint64(x, 1), 10 通过指针访问原子变量 *y atomic.AddUint64(y, 1) 在结构体中定义的原子变量 su.Counter atomic.AddUint64(su.Counter, 1) 在结构体中定义的指针类型的原子变量 *sp.Counter atomic.AddUint64(sp.Counter, 1) 在切片中访问原子变量 au[0] atomic.AddUint64(au[0], 1) 在指针切片中访问原子变量 *ap[0] atomic.AddUint64(ap[0], 1)。 在这些情况中go vet 的 atomic 检查器会给出警告提醒程序员需要使用原子操作来保证多个 goroutine 安全地访问共享变量。正确的做法是使用原子操作函数的返回值而不是将原子操作的结果再次赋值给变量。 4. atomicalign (未集成) check for non-64-bits-aligned arguments to sync/atomic functions atomicalign 包定义了一个分析器用于检查 sync/atomic 函数的非 64 位对齐参数。 在非 32 位平台上如果这些函数的参数变量不是 64 位对齐则会出现错误。 因此调用者有责任安排此类变量的 64 位对齐。 请参阅https://golang.org/pkg/sync/atomic/#pkg-note-BUG 5. bools detects common mistakes involving boolean operators -bools 分析器会检查以下几种常见的布尔表达式错误 在布尔表达式中使用了非布尔类型的值 在布尔表达式中使用了常量 true 或 false但该常量实际上不是布尔类型 在布尔表达式中使用了多余的括号。 更多case 参考: https://github.com/golang/tools/blob/master/go/analysis/passes/bools/testdata/src/a/a.go 6. buildssa(未集成) build SSA-form IR for later passes 包 buildssa 定义了一个分析器用于构造无错误包的 SSA 表示形式并返回其中所有函数的集合。 它本身不报告任何诊断但可以用作其他分析器的输入。 buildssa 是 Go Vet 工具中的一个阶段用于将 Go 代码构建成 SSA 形式Static Single Assignment。Go Vet 使用 SSA 形式来分析 Go 代码并执行静态分析。SSA 形式是一种中间表示形式其中每个变量只赋值一次并且变量的作用域已经确定。 在构建 SSA 形式时Go Vet 还会执行其他优化步骤例如将循环结构转换为尾递归形式以便更容易地进行静态分析。构建 SSA 形式还可以帮助 Go Vet 检测不同函数之间的数据依赖性。 在 go vet 命令行上可以使用 -ssa 标志来控制是否执行 buildssa 阶段。默认情况下buildssa 阶段是开启的。如果您对 Go 代码进行了自己的静态分析并且只需要构建 SSA 形式则可以使用 -ssafalse 来禁用其他分析器只执行 buildssa 阶段。 buildssa 是 Go 语言静态分析工具 go vet 中的一个阶段它的作用是将 Go 代码转换为静态单赋值形式Static Single Assignment简称 SSA以便进行更精确的分析。 在 buildssa 阶段之前go vet 会先对 Go 代码进行语法分析和类型检查。然后buildssa 阶段将 Go 代码转换为 SSA 形式这是一种中间表示形式对于代码分析和优化非常有用。 SSA 形式的一个重要特点是每个变量只能被赋值一次。这样每个变量都有一个唯一的定义点这使得数据流分析更加容易。例如buildssa 阶段可以检测到未初始化的变量、未使用的变量等问题。此外由于 SSA 形式是一种静态单赋值形式它还可以帮助检测一些并发和同步问题。 总之buildssa 阶段是 go vet 中非常重要的一个阶段它将 Go 代码转换为 SSA 形式为后续的分析提供了更精确的基础。 7. buildtag check //go:build and // build directives buildtag 是 Go 语言静态分析工具 go vet 中的一个分析器用于检测 Go 代码中的 // build 和 //go:build 编译指令是否正确使用。 在 Go 语言中// build 和 //go:build 是编译指令用于限制编译时的条件。这些指令允许您为不同的平台、操作系统、架构或编译时选项编写不同的代码。例如您可以使用 // build linux 来指定只在 Linux 上编译该文件或者使用 //go:build !windows 来指定在非 Windows 平台上编译该文件。 然而这些编译指令的错误使用可能会导致编译错误或运行时错误。例如如果编写了不正确的条件可能会导致代码在错误的平台上编译或运行。buildtag 分析器会检测这些问题并向您报告它们。 buildtag 分析器检查以下问题 无效的 // build 或 //go:build 编译指令如拼写错误或语法错误。 不同的文件之间的编译指令不一致。 指令中使用了未定义的标记。 指令中使用了未定义的环境变量。 指令中使用了未定义的 GOOS 或 GOARCH。 在 go vet 命令行上可以使用 -buildtag 标志来控制是否执行 buildtag 分析器。默认情况下buildtag 分析器是开启的。如果您不需要检查 // build 或 //go:build 编译指令可以使用 -buildtagfalse 来禁用它。 当您编写一个跨平台的 Go 项目时可能会使用 // build 或 //go:build 编译指令来限制编译时的条件。例如您可能有一个名为 myutil.go 的文件其中包含以下编译指令 // build linux darwinpackage myutilimport fmtfunc PrintHello() {    fmt.Println(Hello, World!)} 这个文件只会在 Linux 和 Darwin 上编译。如果您在 Windows 上尝试编译这个文件Go 编译器会忽略它并输出以下警告信息 # myutil.\myutil.go:1:2: invalid build comment: unknown compile target linux 这是因为 // build linux darwin 指令只适用于 Linux 和 Darwin而不适用于 Windows。在这种情况下buildtag 分析器会检测到该错误并向您报告它。 此外如果您在其他文件中使用了不同的编译指令例如 // build windowspackage mainimport myutilfunc main() {    myutil.PrintHello()} 这个文件只会在 Windows 上编译。但是由于它使用了 myutil 包而 myutil 包只能在 Linux 和 Darwin 上编译因此会导致编译错误。在这种情况下buildtag 分析器会检测到不一致的编译指令并向您报告它。 总之buildtag 分析器可以帮助您检测和调试 // build 或 //go:build 编译指令中的错误以确保您的代码可以正确地编译和运行。 8. cgocall Package cgocall defines an Analyzer that detects some violations of the cgo pointer passing rules. cgocall 包定义了一个分析器用于检测某些违反 cgo 指针传递规则的行为。 9. composite checks for unkeyed composite literals. 在 Go 语言中unkeyed literals非键入字面量是指在使用 struct 类型的字面量时不使用字段名来给值赋值的情况。在 struct 类型的字面量中可以使用字段名来指定每个字段的值也可以按照 struct 定义中字段的顺序直接给出每个字段的值这就是 unkeyed literals。 例如假设我们有以下定义 type Person struct {    Name string    Age  int} 我们可以使用以下方式创建一个 Person 类型的字面量 p1 : Person{Name: Alice, Age: 30}p2 : Person{Bob, 25} 在上面的例子中p1 使用了字段名来指定每个字段的值而 p2 没有使用字段名而是按照 struct 定义中字段的顺序直接给出了每个字段的值。因此p2 是一个 unkeyed literals。 需要注意的是使用 unkeyed literals 可能会导致代码变得脆弱因为添加或删除字段可能会破坏字面量的结构。因此通常建议在使用 struct 类型的字面量时使用字段名来指定每个字段的值以提高代码的可读性和健壮性。 10. copylock checks for locks erroneously passed by value. 检查是否有错误地按值传递的锁。 “ 无意中复制包含锁的值例如sync.Mutex或sync.WaitGroup可能会导致两个副本都出现故障。 一般这样的值应该通过指针来引用。 copylocks 是 Go 语言静态分析工具 go vet 中的一个分析器用于检测在并发程序中是否正确地使用了 sync.Mutex 或 sync.RWMutex。 在 Go 语言中sync.Mutex 和 sync.RWMutex 是用于保护共享资源的常用同步原语。使用这些类型的互斥锁来保护共享资源时需要确保在访问这些资源时正确地加锁和解锁。如果在访问共享资源时没有正确地加锁和解锁可能会导致数据竞争和其他并发问题。 copylocks 分析器会检查以下问题 在使用 sync.Mutex 或 sync.RWMutex 时是否正确地保护了共享资源并在访问这些资源时正确地加锁和解锁。 在使用 sync.Mutex 或 sync.RWMutex 时是否正确地处理了复制和移动操作。例如如果一个值包含一个互斥锁那么复制或移动该值可能会导致锁的状态不正确。 在 go vet 命令行上可以使用 -copylocks 标志来控制是否执行 copylocks 分析器。默认情况下copylocks 分析器是开启的。如果您不需要检查 sync.Mutex 或 sync.RWMutex 的使用可以使用 -copylocksfalse 来禁用它。 总之copylocks 分析器可以帮助您编写更健壮的并发程序确保在访问共享资源时正确地加锁和解锁并处理复制和移动操作时正确地处理互斥锁的状态。 go vet 是 Go 语言的一个静态分析工具它可以帮助开发者检查代码中可能存在的错误。其中copylocks 是 go vet 的一个检查规则它的作用是检查是否复制了值含有锁或原子类型的值。 当你复制一个包含锁如 sync.Mutex 或 sync.WaitGroup或原子类型如 sync/atomic 包中的类型的值时可能会导致一些非常微妙的错误。例如如果你复制一个 sync.Mutex你可能会得到一个未锁定的新 Mutex这可能会导致数据竞争或其他并发问题。同样复制一个包含原子类型的值也可能导致类似的问题。 以下是一个简单的实例演示了 go vet 的 copylocks 检查如何工作 package mainimport ( sync)type myStruct struct { sync.Mutex value int}func main() { var original myStruct var copy  original // 这里复制了一个含有锁的值 copy.Lock() copy.value  5 copy.Unlock()} 在上述代码中我们定义了一个结构体 myStruct它包含一个 sync.Mutex。然后我们创建了 myStruct 的一个实例然后复制了这个实例。这样就复制了一个含有锁的值这是 go vet 的 copylocks 检查希望避免的。 如果你运行 go vet它会提醒你这个问题 $ go vet main.go# command-line-arguments./main.go:13:13: assignment copies lock value to copy: main.myStruct contains sync.Mutex 在这个错误消息中go vet 正确地指出了 copy 赋值操作复制了锁值这可能会导致未预期的行为。 总的来说go vet 的 copylocks 检查是一个非常有用的工具可以帮助你避免一些可能非常微妙和难以调试的并发问题。 11. ctrlflow(未集成) build a control-flow graph ctrlflow 为函数体提供语法控制流图 (CFG) 的分析。 它记录函数是否无法返回。 其本身不报告任何诊断。 ctrlflow 用于检查 Go 代码中可能存在的控制流问题例如死循环、空循环、无条件跳转等。 package mainfunc main() {    // 死循环    for {    }    // 空循环    for ; ; {    }    // 无条件跳转    goto labellabel:} ctrlflow 会检查上述代码中的所有控制流语句并报告任何可能存在的问题。例如在第一个例子中ctrlflow 会报告一个死循环错误。在第二个例子中ctrlflow 会报告一个空循环错误。在第三个例子中ctrlflow 会报告一个无条件跳转错误。 ctrlflow 是一个非常有用的工具可以帮助开发人员发现代码中可能存在的控制流问题。 12. deepequalerrors(未集成) checks for the use of reflect.DeepEqual with error values. 即 不鼓励使用reflect.DeepEqual比较两个error类型的变量 package mainimport ( errors fmt reflect)func main() { err1 : errors.New(error 1) err2 : errors.New(error 2) // 使用 reflect.DeepEqual 比较两个错误。 if reflect.DeepEqual(err1, err2) {  fmt.Println(The errors are equal.) } else {  fmt.Println(The errors are not equal.) }} 对上面这段代码执行 go vet ./...应该会有相应提示。 但很疑惑并没有.. 相关issue: cmd/vet: warn for reflect.DeepEqual on errors [2] Warn when calling reflect.DeepEqual with errors[3] 13. defers(未集成) report common mistakes in defer statements 当 defer 语句导致非延迟调用 time 时defer 分析器会报告诊断。因为经验表明这几乎总是一个错误。 例如 // start : time.Now()// ...// defer recordLatency(time.Since(start)) // error: call to time.Since is not deferred//// The correct code is://// defer func() { recordLatency(time.Since(start)) }() 即 package mainimport ( fmt time)func main() { start : time.Now() fmt.Println(当前时间:, start) defer recordLatency(time.Since(start)) time.Sleep(3 * time.Second)}func recordLatency(duration time.Duration) { fmt.Println(共耗时:, duration)} 输出并不是预期的3s多而是200多µs 这是因为time.Since会立刻计算不会等defer执行时才算 上面这段代码加defer和不加defer效果一样 正确的写法如下: package mainimport ( fmt time)func main() { start : time.Now() fmt.Println(当前时间:, start) defer func() {  recordLatency(time.Since(start)) }() time.Sleep(3 * time.Second)}func recordLatency(duration time.Duration) { fmt.Println(共耗时:, duration)} 输出 当前时间: 2023-07-25 16:44:26.90604 0800 CST m0.000169751共耗时: 3.001356959s 这个检测项 是2023年新增的 14. directive checks known Go toolchain directives 检查已知的 Go 工具链指令 检查 Go 工具链指令例如 //go:debug 该分析器检查包目录中所有 Go 源文件中已知 Go 工具链指令的问题甚至是那些被 //go:build 约束排除的文件以及所有非 Go 源文件。 对于 //go:debug 请参阅 https://go.dev/doc/godebug分析器检查指令是否仅放置在 Go 源文件中、仅放置在包注释上方以及仅放置在 package main 或 *_test.go 文件中。 将来可能会添加对其他已知指令的支持。 该分析器不检查 //go:build它由 buildtag 分析器处理 这个检测项 也是2023年新增的 15. errorsas checks that the second argument to errors.As is a pointer to a type implementing error 检查 error.As 的第二个参数是否是指向实现错误的类型的指针 1.19新增[4] package mainimport ( errors fmt)func main() { err : MyError{} var target error fmt.Println(errors.As(err, target))}type MyError struct{}func (err *MyError) Error() string { return oops!} “ The error is reported by the go vet command. The go test command automatically runs go vet to report significant problems. The go build command does not run the go vet command. [[Why do I get second argument to errors.As should not be *error build error in test only?](https://stackoverflow.com/questions/75489773/why-do-i-get-second-argument-to-errors-as-should-not-be-error-build-error-in [Why do I get second argument to errors.As should not be *error build error in test only?)] go test命令会自动执行go vet 而执行go build则不会执行go vet 16. fieldalignment(未集成) find structs that would use less memory if their fields were sorted 该分析器查找可以重新排列以使用更少内存的结构并提供 具有最紧凑顺序的建议编辑。 结构体字段排序以占用更少的内存空间 17. findcall(未集成) find calls to a particular function findcall 分析器 报告对特定名称的函数或方法的调用 findcall 包定义了一个分析器用作分析 API 的简单示例和测试。 它报告对由其 -name 标志指定的名称的函数或方法的每次调用的诊断。 它还为每个与名称匹配的声明导出一个事实如果包包含一个或多个此类声明则还导出一个包级fact。 18. framepointer report assembly that clobbers the frame pointer before saving it 报告程序集在保存之前破坏帧指针 framepointer 即FP寄存器 FP寄存器及frame pointer介绍[5] 读取汇编文件 并检查在保存帧指针之前是否破坏了帧指针。如果帧指针被破坏分析器将使用 Pass.Reportf 函数报告错误。 19. httpresponse check for mistakes using HTTP responses 使用 net/http 包时的一个常见错误是在检查确定响应是否有效的错误之前使用defer 延迟关闭 http.Response Body 的函数调用  resp, err : http.Head(url) defer resp.Body.Close() if err ! nil {  log.Fatal(err) } // (defer statement belongs here) 该检查器通过报告此类错误的诊断来帮助发现潜在的 nil dereference bugs nil dereference bugs是什么 nil dereference bugs指的是试图访问null或不是期望对象的对象,从而导致程序崩溃的bug。 在某些语言中,比如Go语言和Rust语言,当尝试访问nil指针时会触发panic或panic。这可以帮助发现编程错误。 一个典型的nil dereference bug案例是: var p *Personp.Name // 崩溃,因为p是nil指针 这里p是nil指针,试图访问p.Name就会导致nil指针引用错误,程序崩溃。 为避免nil dereference bug,我们需要检查指针是否为nil,然后才能安全的访问: if p ! nil {    fmt.Println(p.Name)} 所以总的来说,nil dereference bugs就是由于未检查指针是否为nil从而导致的尝试访问nil指针的错误。 package mainimport ( log net/http)func main() { badHTTPGet()}func badHTTPGet() { res, err : http.Get(http://foo.com)   // 如果err不是nil则res为nil最后调用res.Body.Close() 会panic   defer res.Body.Close() // want using res before checking for errors if err ! nil {  log.Fatal(err) }} 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/httpresponse/testdata/src/a/a.go 20. ifaceassert detect impossible interface-to-interface type assertions 此检查器标记类型断言 v.(T) 和相应的类型转换情况其中 v 的静态类型 V 是不可能实现目标接口 T 的接口。当 V 和 T 包含具有相同名称但不同签名的方法时就会发生这种情况。 // var v interface {//  Read()// }// _  v.(io.Reader) v 中的 Read 方法与 io.Reader 中的 Read 方法具有不同的签名因此该断言无法成功。 package ifaceasserttype Foo interface { Bar()}type FooImpl struct{}func (f *FooImpl) Bar() {}type SomeType struct {}func main() { var f Foo f  FooImpl{} f1 : f.(*FooImpl)  // 这是一个有效的类型断言 f2 : f.(*SomeType) // 这是一个无效的类型断言} 下面这两段仅供参考: ifaceassert是go vet的一个功能,它用于检查接口值是否被有效断言。 举个例子: type Foo interface {    Bar()}type FooImpl struct{}func (f *FooImpl) Bar() {}func main() {    var f Foo     f  FooImpl{}        f1 : f.(*FooImpl)  // 这是一个有效的类型断言    f2 : f.(*SomeType) // 这是一个无效的类型断言    } 这里我们定义了一个Foo接口,有一个FooImpl实现。 然后使用类型断言(f.(*FooImpl))有效地断言了接口值。 但是f.(*SomeType)是无效的类型断言,因为接口值实际类型不是*SomeType。 go vet的ifaceassert可以检测到这个错误: ./main.go:17: invalid type assertion: f.(sometype.*SomeType) (non-interface type *FooImpl on left) 它告诉我们,左边是*FooImpl类型,但是我们尝试断言为*SomeType,这是无效的。 所以ifaceassert可以帮助我们检查类型断言是否有效,避免由于无效类型断言而引起的bug。 当然正确的写法是: f1 : f.(*FooImpl) 使用接口值的实际类型来断言。 总的来说,go vet的ifaceassert用于检查接口类型断言是否有效,避免由于无效类型断言而导致的bug。 ifaceassert是go vet提供的另一个功能,用于检测接口断言是否正确。 接口断言的格式是: obj.(T) 这里obj必须实现接口T,否则会panic。 举个例子: type I interface {    M() }type T struct {}func (t T) M() {}func foo(i I) {    t : i.(T) // 这里可能panic!    t.M()} 这里我们对i执行接口断言,假设i可能是不同类型的对象,那么 i.(T) 可能就会panic。 go vet可以检测到这种情况: ./main.go:11: assertion i.(T) used in non-type assertion context, advisable to check type first            t : i.(T)                   ^   它建议我们先检查i的类型,然后再执行接口断言: t, ok : i.(T)if ok {    t.M() } 使用ok判断变量是否具备该类型,再执行接口断言。 所以,ifaceassert能帮助我们检查接口断言是否合理,避免由于错误的接口断言而导致的panic。 21. inspect (不算分析器) optimize AST traversal for later passes inspect包 定义了一个分析器它为包的语法树提供 AST 检查器 (golang.org/x/tools/go/ast/inspector.Inspector)。 它只是其他分析器的构建块。 另一种分析中的使用示例 package xxxxximport ( go/ast golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis/passes/inspect golang.org/x/tools/go/ast/inspector)var Analyzer  analysis.Analyzer{ ... Requires:       []*analysis.Analyzer{inspect.Analyzer},}func run(pass *analysis.Pass) (interface{}, error) { inspect : pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) inspect.Preorder(nil, func(n ast.Node) {  //... }) return nil, nil} 22. internal(不算分析器) Package analysisutil defines various helper functions used by two or more packages beneath go/analysis. Analysisutil 包定义了 go/analysis 下的两个或多个包使用的各种辅助函数。 即一些公用的辅助函数 23. loopclosure check references to loop variables from within nested functions 检查嵌套函数内对循环变量的引用此分析器报告函数文字引用封闭循环的迭代变量的位置并且循环以这样的方式例如使用 go 或 defer 调用该函数该方式可能比循环迭代寿命更长并且可能观察到错误的变量值。 在此示例中所有延迟函数在循环完成后运行因此所有函数都会观察 v 的最终值。  for _, v : range list {     defer func() {         use(v) // incorrect     }() } 一种解决方法是为循环的每次迭代创建一个新变量  for _, v : range list {     v : v // new var per iteration     defer func() {         use(v) // ok     }() } 下一个示例使用 go 语句并有类似的问题。 此外它还存在数据竞争因为循环更新 v 与访问它的 goroutine 并发。 for _, v : range elem {    go func() {        use(v)  // incorrect, and a data race     }() } 修复与之前相同。 检查器还报告由 golang.org/x/sync/errgroup.Group 启动的 goroutine 中的问题。 这种形式的一个难以发现的变体在并行测试中很常见 func Test(t *testing.T) {     for _, test : range tests {         t.Run(test.name, func(t *testing.T) {             t.Parallel()             use(test) // incorrect, and a data race         })     } } t.Parallel() 调用导致函数的其余部分与循环同时执行。 分析器仅在最后一个语句中报告引用因为它不够深入无法理解可能使引用良性的后续语句的影响。 “最后一条语句”在 if、switch 和 select 等复合语句中递归定义。 请参阅https://golang.org/doc/go_faq.html#closures_and_goroutines 以下供参考: loopclosure是go vet提供的一个功能,用于检测for循环内定义的函数是否引用了循环变量。 举个例子: func main() {    for i : 0; i  5; i {       go func() {            fmt.Println(i)  // 这里引用了循环变量i        }()      }} 这里我们在for循环中定义了一个匿名函数,该函数引用了循环变量i。 由于go是通过复制变量来传入函数的参数,所以循环结束后,所有的函数都会引用同一个i变量的值(5)。 go vet可以检测到这个 Situation: ./main.go:4: i captured by func literal            fmt.Println(i)                          ^   它告诉我们func literal(匿名函数)捕捉到了循环变量i。 正确的写法应该是: for i : 0; i  5; i {   i : i     go func() {       fmt.Println(i)   }()} 使用i : i重新定义i变量,这样每个匿名函数都会引用自己的i变量值。 所以总的来说, loopclosure可以帮助我们检查for循环中的匿名函数是否正确引用了循环变量,避免常见的闭包错误。 24. lostcancel check cancel func returned by context.WithCancel is called The cancellation function returned by context.WithCancel, WithTimeout, and WithDeadline must be called or the new context will remain live until its parent context is cancelled. (The background context is never cancelled.) “ 必须调用 context.WithCancel、WithTimeout 和 WithDeadline 返回的取消函数否则新上下文将保持活动状态直到其父上下文被取消。 后台上下文永远不会被取消。 这段文本是关于 Go 语言中使用 context 包创建上下文的函数 context.WithCancel、context.WithTimeout 和 context.WithDeadline 的使用说明。 在 Go 语言中context 包提供了一种用于在多个 Goroutine 之间传递取消信号和截止时间的机制以便在合适的时候取消或超时某个操作。 这段文本中提到的内容是指当使用 context.WithCancel、context.WithTimeout 或 context.WithDeadline 函数创建一个新的上下文时会返回一个取消函数cancel function。这个取消函数可以用来取消上下文即停止所有使用该上下文派生出来的 Goroutine。 然而如果你创建了一个新的上下文使用上述函数之一但没有调用返回的取消函数那么这个新的上下文将一直处于活动状态不会自动取消。这意味着其中的 Goroutine 将不会被释放会继续执行。这可能导致资源泄漏或程序逻辑错误。 需要注意的是背景上下文background context是一个特殊的上下文它永远不会被取消因为它是所有上下文的根节点。在使用 context.Background() 创建背景上下文时不需要担心未调用取消函数的问题因为它本身永远不会被取消。 所以如果你在代码中使用了 context.WithCancel、context.WithTimeout 或 context.WithDeadline 创建了新的上下文请确保在不再需要该上下文时及时调用返回的取消函数以便及时释放相关资源并停止相关 Goroutine 的执行。 package mainimport ( context time)func main() { ctx, _ : context.WithTimeout(context.Background(), 1*time.Second) go func() {  // 忘记调用cancel,导致context泄漏 }() _  ctx time.Sleep(2 * time.Second)} lostcancel可以帮助我们检查是否正确地调用了context的cancel函数,避免context泄漏问题。 25. nilfunc check for useless comparisons between functions and nil 一种无用的比较是类似 f nil 而不是 f() nil 的比较。 package mainfunc main() { if shuang  nil {  print(123) }}func shuang() { print(678)} 26. nilness(未集成) check for redundant or impossible nil comparisons 检查冗余或不可能的零比较 包 nilness 检查 SSA 函数的控制流图并报告错误例如 nil 指针取消引用和退化 nil 指针比较。 nilness 检查器检查包中每个函数的控制流图并报告 nil 指针取消引用、退化 nil 指针以及 nil 值的恐慌。 简并比较的形式为 xnil 或 x!nil其中 x 静态地已知为 nil 或非 nil。 这些常常是错误特别是与控制流相关的错误。 检查带有 nil 值的恐慌因为它们无法被检测到 相关case参考: https://github.com/golang/tools/blob/master/go/analysis/passes/nilness/testdata/src/a/a.go 2023年新增 27. pkgfact(未集成) gather name/value pairs from constant declarations 从常量声明中收集 name/value 对 pkgfact 包是包事实机制(package fact mechanism)的演示和测试。 pkgfact 分析的输出是一组从分析的包及其导入的依赖项中收集的键/值对。 每个键/值对都来自一个顶级常量声明其名称以“_”开头和结尾。 例如 package pconst _greeting_   helloconst _audience_   world 包 p 的 pkgfact 分析输出将是 {greeting: hello, audience: world}. In addition, the analysis reports a diagnostic at each import showing which key/value pairs it contributes. package fact mechanism是什么 Package fact mechanism是Go语言的一种机制,它可以在编译时收集包的信息,并且这些信息可以在运行时被访问。 Go收集的两种fact信息是: Package facts: 包级别的信息。包括包的路径、名字、导入路径等。 Type facts:类型级别的信息。包括类型的大小、内置方法等。 这些fact信息会被记录在一个叫.a的文件中,这个文件会随代码一起编译。然后在运行时,程序可以通过reflection访问这些信息。 举个例子,要获取一个包的名称,可以这样做: import (    reflect    runtime)func main() {     pname :  runtime.FuncForPC(reflect.ValueOf(main).Pointer()).Name()     parts : strings.Split(pname, .)    fmt.Println(parts[len(parts)-1])  // prints main} 这里使用reflect获取main函数的指针,然后通过runtime获取函数名称。这个名称包含了包名,因此我们可以提取出包名。 Package fact mechanism让程序可以在运行时获取编译时已知的信息。比如包名、导入路径等。 总的来说: Go在编译时收集包级别和类型级别的信息 这些信息储存在.a文件中 程序可以在运行时通过reflection访问这些信息 Package facts mechanism让程序可以获取编译时已知的元信息 以下内容供参考,未必准确: pkgfact是一个go vet提供的功能,它用于检查包级别的fact信息。包括: 包是否被导入但未使用 多个包是否引用同一个导入路径 我们来看个例子: import (    fmt      math  // 这个包未使用  )func main() {    fmt.Println(hello)} 这里我们导入了math包但是未使用,go vet可以检查到: ./main.go:3: import of package math is unused         math             ^^^   它提示math包被导入但未使用。 另一个例子: import (    fmt       encoding/json)import . morejson // 使用了相同的导入路径 这里同一个导入路径json被多个包导入,go vet可以检测到: ./main.go:6: import redefinition:        encoding/json previously imported at ./main.go:3        morejson imported here 它提示有import redefinition。 通过检查包的fact信息,pkgfact可以帮助我们: 检测包是否被导入但未使用 检测import是否存在redefinition 避免因此产生一些潜在的bug 总的来说: pkgfact用于检查包级别的fact信息,以保持imports的正确性。它会检查: 包是否被导入但未使用 是否有import redefinition的情况 28. printf check consistency of Printf format strings and arguments 检查 Printf 格式字符串和参数的一致性 package mainimport fmtfunc main() { fmt.Printf(%d %s, 1) // ./main.go:7:2: fmt.Printf format %s reads arg #2, but call has 1 arg fmt.Printf(%s, 1) // ./main.go:9:2: fmt.Printf format %s has arg 1 of wrong type int} 29. reflectvaluecompare(未集成) check for comparing reflect.Value values with or reflect.DeepEqual 检查将reflect.Value值与或reflect.DeepEqual进行比较 ReflectValueCompare 检查器查找以下形式的表达式  v1  v2 v1 ! v2 reflect.DeepEqual(v1, v2) 其中 v1 或 v2 是 Reflect.Values。 直接比较reflect.Values几乎肯定是不正确的因为它比较的是reflect包的内部表示而不是底层值。 可能的目的是  v1.Interface()  v2.Interface() v1.Interface() ! v2.Interface() reflect.DeepEqual(v1.Interface(), v2.Interface()) 相关case参考: https://github.com/golang/tools/blob/master/go/analysis/passes/reflectvaluecompare/testdata/src/a/a.go 30. shadow(未集成) check for possible unintended shadowing of variables 检查变量可能出现的意外阴影 该分析器检查隐藏变量。 隐藏变量是在内部作用域中声明的变量其名称和类型与外部作用域中的变量相同并且在声明内部变量之后提及外部变量。 这个定义可以细化该模块产生太多误报并且默认情况下尚未启用。 例如: func BadRead(f *os.File, buf []byte) error {  var err error  for {   n, err : f.Read(buf) // shadows the function variable err   if err ! nil {    break // causes return of wrong value   }   foo(buf)  }  return err } 31. shift check for shifts that equal or exceed the width of the integer 检查是否存在等于或超过整数宽度的移位 package shiftimport unsafefunc ShiftTest() { var i8 int8 _  i8  7 _  (i8  1)  8 // want .i8 . 1. .8 bits. too small for shift of 8 _  i8  (7  1) // want i8 .8 bits. too small for shift of 8 _  i8  8       // want i8 .8 bits. too small for shift of 8 i8  8          // want i8 .8 bits. too small for shift of 8 i8  8          // want i8 .8 bits. too small for shift of 8 var i16 int16 _  i16  15 _  i16  16 // want i16 .16 bits. too small for shift of 16 _  i16  16 // want i16 .16 bits. too small for shift of 16 i16  16    // want i16 .16 bits. too small for shift of 16 i16  16    // want i16 .16 bits. too small for shift of 16 var i32 int32 _  i32  31 _  i32  32 // want i32 .32 bits. too small for shift of 32 _  i32  32 // want i32 .32 bits. too small for shift of 32 i32  32    // want i32 .32 bits. too small for shift of 32 i32  32    // want i32 .32 bits. too small for shift of 32 var i64 int64 _  i64  63 _  i64  64 // want i64 .64 bits. too small for shift of 64 _  i64  64 // want i64 .64 bits. too small for shift of 64 i64  64    // want i64 .64 bits. too small for shift of 64 i64  64    // want i64 .64 bits. too small for shift of 64 var u8 uint8 _  u8  7 _  u8  8 // want u8 .8 bits. too small for shift of 8 _  u8  8 // want u8 .8 bits. too small for shift of 8 u8  8    // want u8 .8 bits. too small for shift of 8 u8  8    // want u8 .8 bits. too small for shift of 8 var u16 uint16 _  u16  15 _  u16  16 // want u16 .16 bits. too small for shift of 16 _  u16  16 // want u16 .16 bits. too small for shift of 16 u16  16    // want u16 .16 bits. too small for shift of 16 u16  16    // want u16 .16 bits. too small for shift of 16 var u32 uint32 _  u32  31 _  u32  32 // want u32 .32 bits. too small for shift of 32 _  u32  32 // want u32 .32 bits. too small for shift of 32 u32  32    // want u32 .32 bits. too small for shift of 32 u32  32    // want u32 .32 bits. too small for shift of 32 var u64 uint64 _  u64  63 _  u64  64  // want u64 .64 bits. too small for shift of 64 _  u64  64  // want u64 .64 bits. too small for shift of 64 u64  64     // want u64 .64 bits. too small for shift of 64 u64  64     // want u64 .64 bits. too small for shift of 64 _  u64  u64 // Non-constant shifts should succeed. var i int _  i  31 const in  8 * unsafe.Sizeof(i) _  i  in // want too small for shift _  i  in // want too small for shift i  in    // want too small for shift i  in    // want too small for shift const ix  8*unsafe.Sizeof(i) - 1 _  i  ix _  i  ix i  ix i  ix var u uint _  u  31 const un  8 * unsafe.Sizeof(u) _  u  un // want too small for shift _  u  un // want too small for shift u  un    // want too small for shift u  un    // want too small for shift const ux  8*unsafe.Sizeof(u) - 1 _  u  ux _  u  ux u  ux u  ux var p uintptr _  p  31 const pn  8 * unsafe.Sizeof(p) _  p  pn // want too small for shift _  p  pn // want too small for shift p  pn    // want too small for shift p  pn    // want too small for shift const px  8*unsafe.Sizeof(p) - 1 _  p  px _  p  px p  px p  px const oneIf64Bit  ^uint(0)  63 // allow large shifts of constants; they are used for 32/64 bit compatibility tricks var h uintptr h  h8 | (h  (8 * (unsafe.Sizeof(h) - 1))) h  8 * unsafe.Sizeof(h) // want too small for shift h  7 * unsafe.Alignof(h) h  8 * unsafe.Alignof(h) // want too small for shift} 执行go vet main.go后输出: # command-line-arguments./main.go:8:6: (i8  1) (8 bits) too small for shift of 8./main.go:9:6: i8 (8 bits) too small for shift of 8./main.go:10:6: i8 (8 bits) too small for shift of 8./main.go:11:2: i8 (8 bits) too small for shift of 8./main.go:12:2: i8 (8 bits) too small for shift of 8./main.go:15:6: i16 (16 bits) too small for shift of 16./main.go:16:6: i16 (16 bits) too small for shift of 16./main.go:17:2: i16 (16 bits) too small for shift of 16./main.go:18:2: i16 (16 bits) too small for shift of 16./main.go:21:6: i32 (32 bits) too small for shift of 32./main.go:22:6: i32 (32 bits) too small for shift of 32./main.go:23:2: i32 (32 bits) too small for shift of 32./main.go:24:2: i32 (32 bits) too small for shift of 32./main.go:27:6: i64 (64 bits) too small for shift of 64./main.go:28:6: i64 (64 bits) too small for shift of 64./main.go:29:2: i64 (64 bits) too small for shift of 64./main.go:30:2: i64 (64 bits) too small for shift of 64./main.go:33:6: u8 (8 bits) too small for shift of 8./main.go:34:6: u8 (8 bits) too small for shift of 8./main.go:35:2: u8 (8 bits) too small for shift of 8./main.go:36:2: u8 (8 bits) too small for shift of 8./main.go:39:6: u16 (16 bits) too small for shift of 16./main.go:40:6: u16 (16 bits) too small for shift of 16./main.go:41:2: u16 (16 bits) too small for shift of 16./main.go:42:2: u16 (16 bits) too small for shift of 16./main.go:45:6: u32 (32 bits) too small for shift of 32./main.go:46:6: u32 (32 bits) too small for shift of 32./main.go:47:2: u32 (32 bits) too small for shift of 32./main.go:48:2: u32 (32 bits) too small for shift of 32./main.go:51:6: u64 (64 bits) too small for shift of 64./main.go:52:6: u64 (64 bits) too small for shift of 64./main.go:53:2: u64 (64 bits) too small for shift of 64./main.go:54:2: u64 (64 bits) too small for shift of 64./main.go:60:6: i (64 bits) too small for shift of 64./main.go:61:6: i (64 bits) too small for shift of 64./main.go:62:2: i (64 bits) too small for shift of 64./main.go:63:2: i (64 bits) too small for shift of 64./main.go:73:6: u (64 bits) too small for shift of 64./main.go:74:6: u (64 bits) too small for shift of 64./main.go:75:2: u (64 bits) too small for shift of 64./main.go:76:2: u (64 bits) too small for shift of 64./main.go:86:6: p (64 bits) too small for shift of 64./main.go:87:6: p (64 bits) too small for shift of 64./main.go:88:2: p (64 bits) too small for shift of 64./main.go:89:2: p (64 bits) too small for shift of 64./main.go:100:2: h (64 bits) too small for shift of 64./main.go:102:2: h (64 bits) too small for shift of 64 以下内容供参考: shift是go vet提供的一个功能,它用于检查移位操作是否正确。 在Go语言中,不同类型的数值 shifting是不一样的。 uint类型接受无符号移位 int类型接受有符号移位 举个例子: var a uint  1a  2 // 4var b int  1b  2 // -8 对uint做左移是无符号的,结果是4。 而对int做左移是有符号的,结果是-8。 go vet可以检测到这种混用: ./main.go:4: result of left shift of int by uint will be uint        b  2           ^^ 它提示左移的结果将是uint类型。 为了避免混用不同类型的移位操作,我们应该把它们转换为相同的类型: b  uint(2)  // 强制转换为uint类型 所以,shift功能主要用于检查: int和uint之间的移位混用 是否使用正确的类型转换 以避免由此产生的bug。 总的来说: int和uint的移位结果不同 shift可以检查int和uint之间是否存在移位混用 通过提示添加类型转换,可以避免潜在的bug 32. sigchanyzer check for unbuffered channel of os.Signal 检查 os.Signal 的无缓冲通道 该检查器报告这种形式的调用表达式 signal.Notify(c -chan os.Signal, sig ...os.Signal) 其中 c 是无缓冲通道可能存在丢失信号的风险。 package sigchanyzerimport ( os os/signal)func g() { c : make(chan os.Signal) signal.Notify(c, os.Interrupt) // want misuse of unbuffered os.Signal channel as argument to signal.Notify _  -c} 执行 go vet main.go 后输出 # command-line-arguments./main.go:10:2: misuse of unbuffered os.Signal channel as argument to signal.Notify 更多case参考: https://github.com/golang/tools/blob/master/go/analysis/passes/sigchanyzer/testdata/src/a/a.go 以下内容供参考: sigchanyzer是go vet提供的一个功能,它用于检查信号处理是否正确。 在Go语言中,我们使用signal包来处理OS信号,像SIGINT、SIGTERM等。 举个例子,监听SIGINT信号: signal.Notify(c, os.Interrupt)for {    select {    case -c:        // 处理SIGINT信号             } } 这里我们使用signal.Notify注册了SIGINT信号,然后不停检查channel是否有信号。 go vet可以检查我们是否正确处理了信号: signal.Notify(c, os.Interrupt)-c // 错误! 循环只检查一次channel 这里我们只检查一次channel,没有正确处理SIGINT信号。 go vet可以检测到: ./main.go:5: ignoring subsequent SIGINT after first       -c            ^   所以sigchanyzer主要可以检查是否: 正确使用select监听信号channel 在循环中多次检查信号channel 以确保全部信号都被处理。 通过go vet,我们可以避免 accidentally ignoring OS signals的错误。 总的来说,sigchanyzer用来检查信号处理是否正确,包括: 使用select机制监听信号 在循环中多次检查信号channel 避免忽略信号 以确保我们的代码能正确处理OS信号。 33. slog check for invalid structured logging calls slog 检查器从 log/slog 包中查找采用交替键值对的函数调用。 它报告键位置中的参数既不是字符串也不是 slog.Attr 且最终键缺少其值的调用。 例如它会报告 slog.Warn(message, 11, k) // slog.Warn arg 11 should be a string or a slog.Attr 和 slog.Info(message, k1, v1, k2) // call to slog.Info missing a final value 更多case参考: https://github.com/golang/tools/blob/master/go/analysis/passes/slog/testdata/src/a/a.go 2023年新增 34. sortslice(未集成) check the argument type of sort.Slice sort.Slice 需要切片类型的参数。 检查一下传递给 sort.Slice 的 interface{} 值实际上是一个切片 package mainimport sortfunc main() { i : 5 sortFn : func(i, j int) bool { return false } sort.Slice(i, sortFn)         // want sort.Slices argument must be a slice; is called with int sort.SliceStable(i, sortFn)   // want sort.SliceStables argument must be a slice; is called with int sort.SliceIsSorted(i, sortFn) // want sort.SliceIsSorteds argument must be a slice; is called with int} 执行 go vet main.go后未生效这是因为tools项目中提供了但是go项目中未集成进来 更多case参考: https://github.com/golang/tools/blob/master/go/analysis/passes/sortslice/testdata/src/a/a.go 当前go vet中集成进来的分析器见 https://github.com/golang/go/blob/master/src/cmd/vet/main.go#L47 可以研究下为什么没有集成进去是不是忘了.. 看起来不是https://github.com/golang/go/tree/master/src/cmd/vet 这里提到 Over time many checks have been added to vets suite, but many more have been rejected as not appropriate for the tool. 35. stdmethods checks for misspellings in the signatures of methods similar to well-known interfaces 检查类似于众所周知的接口的方法签名中的拼写错误。 有时类型可能旨在满足接口但可能由于其方法签名中的错误而无法满足接口的要求。 例如这个 WriteTo 方法的结果应该是 (int64, error)而不是 error以满足 io.WriterTo  type myWriterTo struct{...} func (myWriterTo) WriteTo(w io.Writer) error { ... } 此检查可确保名称与标准库中几个众所周知的接口方法之一匹配的每个方法都具有该接口的正确签名。 检查的方法名称包括 Format GobEncode GobDecode MarshalJSON MarshalXML Peek ReadByte ReadFrom ReadRune Scan Seek UnmarshalJSON UnreadByte UnreadRune WriteByte WriteTo 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/stdmethods/testdata/src/a/a.go 36. stringintconv check for string(int) conversions 此检查器标记 string(x) 形式的转换其中 x 是整数但不是字节byte或符文rune类型。 不鼓励进行此类转换因为它们返回 Unicode 代码点 x 的 UTF-8 表示形式而不是人们所期望的 x 的十进制字符串表示形式。 此外如果 x 表示无效代码点则不能静态拒绝转换。 对于打算使用代码点的转换请考虑将其替换为 string(rune(x))。 否则strconv.Itoa 及其等效项返回所需基数中值的字符串表示形式。 package stringintconvtype A stringtype B  stringtype C inttype D  uintptrfunc StringTest() { var (  i int  j rune  k byte  l C  m D  n  []int{0, 1, 2}  o struct{ x int } ) const p  0 _  string(i) // want ^conversion from int to string yields a string of one rune, not a string of digits \(did you mean fmt\.Sprint\(x\)\?\)$ _  string(j) _  string(k) _  string(p)    // want ^conversion from untyped int to string yields a string of one rune, not a string of digits \(did you mean fmt\.Sprint\(x\)\?\)$ _  A(l)         // want ^conversion from C \(int\) to A \(string\) yields a string of one rune, not a string of digits \(did you mean fmt\.Sprint\(x\)\?\)$ _  B(m)         // want ^conversion from uintptr to B \(string\) yields a string of one rune, not a string of digits \(did you mean fmt\.Sprint\(x\)\?\)$ _  string(n[1]) // want ^conversion from int to string yields a string of one rune, not a string of digits \(did you mean fmt\.Sprint\(x\)\?\)$ _  string(o.x)  // want ^conversion from int to string yields a string of one rune, not a string of digits \(did you mean fmt\.Sprint\(x\)\?\)$} 执行 go vet main.go 输出: # command-line-arguments./main.go:22:6: conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)./main.go:25:6: conversion from untyped int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)./main.go:26:6: conversion from C (int) to A (string) yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)./main.go:27:6: conversion from uintptr to B (string) yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)./main.go:28:6: conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)./main.go:29:6: conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?) 37. structtag checks struct field tags are well formed 检查结构字段标签的格式是否正确 检查结构体字段标签是否符合 reflect.StructTag.Get 还报告与未导出字段一起使用的某些结构标签json、xml package structtagtype StructTagTest struct { A   int hello            // want hello not compatible with reflect.StructTag.Get: bad syntax for struct tag pair B   int \tx:\y\        // want not compatible with reflect.StructTag.Get: bad syntax for struct tag key C   int x:\y\\tx:\y\ // want not compatible with reflect.StructTag.Get D   int x:y            // want not compatible with reflect.StructTag.Get: bad syntax for struct tag value E   int ct\brl:\char\  // want not compatible with reflect.StructTag.Get: bad syntax for struct tag pair F   int :emptykey      // want not compatible with reflect.StructTag.Get: bad syntax for struct tag key G   int x:noEndQuote    // want not compatible with reflect.StructTag.Get: bad syntax for struct tag value H   int x:trunc\x0     // want not compatible with reflect.StructTag.Get: bad syntax for struct tag value I   int x:foo,y:bar  // want not compatible with reflect.StructTag.Get: key:.value. pairs not separated by spaces J   int x:fooy:bar   // want not compatible with reflect.StructTag.Get: key:.value. pairs not separated by spaces OK0 int x:y u:v w: OK1 int x:y:z u:v w: // note multiple colons. OK2 int k0:\values contain spaces\ k1:\literal\ttabs\ k2:\and\\tescaped\\tabs\ OK3 int under_scores:and CAPS:ARE_OK} 执行 go vet main.go后输出: # command-line-arguments./main.go:4:2: struct field tag hello not compatible with reflect.StructTag.Get: bad syntax for struct tag pair./main.go:5:2: struct field tag        x:y not compatible with reflect.StructTag.Get: bad syntax for struct tag key./main.go:6:2: struct field tag x:y  x:y not compatible with reflect.StructTag.Get: key:value pairs not separated by spaces./main.go:7:2: struct field tag x:y not compatible with reflect.StructTag.Get: bad syntax for struct tag value./main.go:8:2: struct field tag ct\brl:\char\ not compatible with reflect.StructTag.Get: bad syntax for struct tag pair./main.go:9:2: struct field tag :emptykey not compatible with reflect.StructTag.Get: bad syntax for struct tag key./main.go:10:2: struct field tag x:noEndQuote not compatible with reflect.StructTag.Get: bad syntax for struct tag value./main.go:11:2: struct field tag x:trunc\x0 not compatible with reflect.StructTag.Get: bad syntax for struct tag value./main.go:12:2: struct field tag x:foo,y:bar not compatible with reflect.StructTag.Get: key:value pairs not separated by spaces./main.go:13:2: struct field tag x:fooy:bar not compatible with reflect.StructTag.Get: key:value pairs not separated by spaces 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/structtag/testdata/src/a/a.go 38. testinggoroutine *report calls to (testing.T).Fatal from goroutines started by a test 报告由测试启动的 goroutine 对 (*testing.T).Fatal 的调用 突然终止测试的函数例如 *testing.T 的 Fatal、Fatalf、FailNow 和 Skip{,f,Now} 方法必须从测试 goroutine 本身调用。 该检查器检测由测试启动的 goroutine 中发生的对这些函数的调用。 例如 func TestFoo(t *testing.T) {   go func() {        t.Fatal(oops) // error: (*T).Fatal called from non-test goroutine    }() } package testinggoroutineimport ( sync testing)func TestBadFatalf(t *testing.T) { var wg sync.WaitGroup defer wg.Wait() for i : 0; i  2; i {  wg.Add(1)  go func(id int) {   defer wg.Done()   t.Fatalf(TestFailed: id  %v\n, id) // want call to .T.Fatalf from a non-test goroutine  }(i) }} 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/testinggoroutine/testdata/src/a/a.go 39. tests check for common mistaken usages of tests and examples 这个分析器 运行测试、基准、模糊测试和示例功能检查格式错误的名称、错误的签名和记录不存在的标识符的示例。 请参阅 golang.org/pkg/testing 中的包测试文档了解测试、基准和示例强制执行的约定。 这一块有不少todo可以去看看 相关case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/tests/testdata/src/a/a_test.go 40. timeformat check for calls of (time.Time).Format or time.Parse with 2006-02-01 查找格式为 2006-02-01 (yyyy-dd-mm) 的时间格式。 在国际上“yyyy-dd-mm”不会出现在通用日历日期标准中因此更可能是 2006-01-02 (yyyy-mm-dd) package timeformatimport timefunc hasError() { a, _ : time.Parse(2006-02-01 15:04:05, 2021-01-01 00:00:00) // want 2006-02-01 should be 2006-01-02 a.Format(2006-02-01)                                           // want 2006-02-01 should be 2006-01-02 a.Format(2006-02-01 15:04:05)                                  // want 2006-02-01 should be 2006-01-02 const c  2006-02-01 a.Format(c) // want 2006-02-01 should be 2006-01-02} 执行go vet main.go后输出: # command-line-arguments./main.go:6:22: 2006-02-01 should be 2006-01-02./main.go:7:12: 2006-02-01 should be 2006-01-02./main.go:8:12: 2006-02-01 should be 2006-01-02./main.go:11:11: 2006-02-01 should be 2006-01-02 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/timeformat/testdata/src/a/a.go 41. unmarshal report passing non-pointer or non-interface values to unmarshal 报告对 json.Unmarshal 等函数的调用但其中参数类型不是指针或接口的情况。 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/unmarshal/testdata/src/a/a.go 42. unreachable check for unreachable code 该分析器会查找执行永远无法到达的语句因为它们前面有 return 语句、对panic的调用、无限循环或类似的结构。 package unreachablefunc _() int { print(1) return 2 println() // want unreachable code}func _() int {L: print(1) goto L println() // want unreachable code}func _() int { print(1) panic(2) println() // want unreachable code} 输出: # command-line-argumentsvet: ./main.go:7:1: missing return 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/unreachable/testdata/src/a/a.go 43. unsafeptr check for invalid conversions of uintptr to unsafe.Pointer 检查 uintptr 到 unsafe.Pointer 的无效转换 报告可能错误地使用 unsafe.Pointer 将整数转换为指针。 如果从 uintptr 到 unsafe.Pointer 的转换意味着内存中存在一个保存指针值的 uintptr 类型的字则该转换无效因为该字对于堆栈复制和垃圾收集器来说是不可见的。 package unsafeptrimport unsafefunc f() { var x unsafe.Pointer var y uintptr x  unsafe.Pointer(y) // want possible misuse of unsafe.Pointer y  uintptr(x) // only allowed pointer arithmetic is ptr /-/^ num. // numptr is technically okay but still flagged: write ptrnum instead. x  unsafe.Pointer(uintptr(x)  1) x  unsafe.Pointer(((uintptr((x)))  1)) x  unsafe.Pointer(1  uintptr(x))          // want possible misuse of unsafe.Pointer x  unsafe.Pointer(uintptr(x)  uintptr(x)) // want possible misuse of unsafe.Pointer} 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/unsafeptr/testdata/src/a/a.go 44. unusedresult checks for unused results of calls to certain pure functions 有些函数例如 fmt.Errorf会返回结果并且没有副作用因此丢弃结果始终是错误的。 其他函数可能会返回一个不能被忽略的错误或者一个必须调用的清理操作。 当调用结果被忽略时该分析器会报告对此类函数的调用。 可以使用标志来控制该组函数。 package unusedresultimport ( bytes errors fmt . fmt)func _() { fmt.Errorf() // want result of fmt.Errorf call not used _  fmt.Errorf() errors.New() // want result of errors.New call not used err : errors.New() err.Error() // want result of \(error\).Error call not used var buf bytes.Buffer buf.String() // want result of \(\*bytes.Buffer\).String call not used fmt.Sprint()  // want result of fmt.Sprint call not used fmt.Sprintf() // want result of fmt.Sprintf call not used Sprint()  // want result of fmt.Sprint call not used Sprintf() // want result of fmt.Sprintf call not used} 输出: # command-line-arguments./main.go:11:12: result of fmt.Errorf call not used./main.go:14:12: result of errors.New call not used./main.go:17:11: result of (error).Error call not used./main.go:20:12: result of (*bytes.Buffer).String call not used./main.go:22:12: result of fmt.Sprint call not used./main.go:23:13: result of fmt.Sprintf call not used./main.go:25:8: result of fmt.Sprint call not used./main.go:26:9: result of fmt.Sprintf call not used 相关case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/unusedresult/testdata/src/a/a.go 45. unusedwrite(未集成) checks for unused writes to the elements of a struct or array object 检查对结构或数组对象元素的未使用写入 报告从未读取的结构体字段和数组的写入实例。 具体来说当复制结构体对象或数组时编译器会隐式复制其元素并且写入此副本的任何元素都不会对原始对象执行任何操作。 例如: type T struct { x int }func f(input []T) { for i, v : range input {  // v is a copy  v.x  i  // unused write to field x }} 另一个例子是关于非指针接收者:  type T struct { x int } func (t T) f() {  // t is a copy  t.x  i  // unused write to field x } 更多case参考 https://github.com/golang/tools/blob/master/go/analysis/passes/unusedwrite/testdata/src/a/unusedwrite.go tools项目中提供了但是go项目中未集成进来 46. usesgenerics(未集成) checks for usage of generic features added in Go 1.18 检查 Go 1.18 中添加的泛型功能的使用情况 usegenerics 分析报告包是否直接或间接使用与 Go 中泛型编程相关的某些功能。 相关case参考: https://github.com/golang/tools/tree/master/go/analysis/passes/usesgenerics/testdata/src tools项目中提供了但是go项目中未集成进来 参考资料 [1] asmdecl: https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/asmdecl [2] cmd/vet: warn for reflect.DeepEqual on errors : https://github.com/golang/go/issues/16748 [3] Warn when calling reflect.DeepEqual with errors: https://github.com/golang/lint/issues/232 [4] 1.19新增: https://tip.golang.org/doc/go1.19#vet [5] FP寄存器及frame pointer介绍: https://blog.csdn.net/zzsfqiuyigui/article/details/22992957 本文由 mdnice 多平台发布
http://www.zqtcl.cn/news/355287/

相关文章:

  • 网站需求分析模板深圳3d制作
  • 宿迁网站建设推广公司wordpress忘记密码了
  • 成都双语网站开发flat wordpress
  • 大连做公司网站的公司网络营销的网站
  • 做网站 人工智能怎么做商业服务网站
  • 自助建站公司四平市住房和城乡建设部网站
  • 淄博网站seo价格世界新闻最新消息
  • 网站开发 毕业答辩pptwordpress qq邮箱订阅
  • 国家icp备案网站群辉域名登录wordpress
  • 仙居住房和城乡建设规划局网站可以做思维导图的网站
  • 企业网站建设费怎么入账石家庄定制网站建设服务
  • 遂宁建设网站如何搭建微信公众号平台
  • 咖啡网站源码公司网站手机版
  • 新能源网站开发网站做5级分销合法吗
  • 西安建设网站排名简约风网站首页怎么做
  • 安远做网站做服务网站要多少钱
  • 功能网站模板电商平台项目商业计划书
  • 阿里巴巴国际站入驻费用及条件广州做网站比较好的公司
  • 淄博营销网站建设阳泉营销型网站建设费用
  • 珠海网站开发定制常德网站建设详细策划
  • 做电影网站侵权哈尔滨网站开发
  • 中国联通网站备案系统Wordpress建立空白页面
  • 郑州网站建设 郑州网站制作wordpress删除模板
  • 北京网站设计培训wordpress vps 伪静态
  • 做网站和编程有关系吗seo百家外链网站
  • 网站新闻怎么写最新事故案例100例
  • 网站中的表格seo宣传网站
  • 河南锦路路桥建设有限公司网站网站建设会考什么
  • 高校网站建设研究意义餐饮vi设计案例
  • 触屏手机网站网站建设功能模块价格