that do not guarantee all reports are genuine problems, but it can find errors
not caught by the compilers.
+By default all checks are performed, but if explicit flags are provided, only
+those identified by the flags are performed.
+
Available checks:
-1. Printf family
+1. Printf family, flag -printf
Suspicious calls to functions in the Printf family, including any functions
with these names:
It also checks for errors such as using a Writer as the first argument of
Printf.
-2. Methods
+2. Methods, flag -methods
Non-standard signatures for methods with familiar names, including:
Format GobEncode GobDecode MarshalJSON MarshalXML
UnmarshalJSON UnreadByte UnreadRune WriteByte
WriteTo
-3. Struct tags
+3. Struct tags, flag -structtags
Struct tags that do not follow the format understood by reflect.StructTag.Get.
+4. Untagged composite literals, flag -composites
+
+Composite struct literals that do not used the type-tagged syntax.
+
+
Usage:
go tool vet [flag] [file.go ...]
go tool vet [flag] [directory ...] # Scan all .go files under directory, recursively
-The flags are:
+The other flags are:
-v
Verbose mode
-printfuncs
var verbose = flag.Bool("v", false, "verbose")
var exitCode = 0
+// Flags to control which checks to perform
+var (
+ vetAll = flag.Bool("all", true, "check everything; disabled if any explicit check is requested")
+ vetMethods = flag.Bool("methods", false, "check that canonically named methods are canonically defined")
+ vetPrintf = flag.Bool("printf", false, "check printf-like invocations")
+ vetStructTags = flag.Bool("structtags", false, "check that struct field tags have canonical format")
+ vetUntaggedLiteral = flag.Bool("composites", false, "check that composite literals used type-tagged elements")
+)
+
// setExit sets the value for os.Exit when it is called, later. It
// remembers the highest value.
func setExit(err int) {
flag.Usage = Usage
flag.Parse()
+ // If a check is named explicitly, turn off the 'all' flag.
+ if *vetMethods || *vetPrintf || *vetStructTags || *vetUntaggedLiteral {
+ *vetAll = false
+ }
+
if *printfuncs != "" {
for _, name := range strings.Split(*printfuncs, ",") {
if len(name) == 0 {
}
func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
+ if !*vetMethods && !*vetAll {
+ return
+ }
// Expected input/output.
expect, ok := canonicalMethods[id.Name]
if !ok {
printer.Fprint(&f.b, f.fset, actual)
return f.b.String() == expect
}
+
+func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
+}
+
+type BadInterfaceUsedInTests interface {
+ ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
+}
// checkCall triggers the print-specific checks if the call invokes a print function.
func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
+ if !*vetPrintf && !*vetAll {
+ return
+ }
name := strings.ToLower(Name)
if skip, ok := printfList[name]; ok {
f.checkPrintf(call, Name, skip)
f.Warnf(0, "%#s", "hello") // ERROR "unrecognized printf flag"
}
-type BadTypeUsedInTests struct {
- X int "hello" // ERROR "struct field tag"
-}
-
-func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
-}
-
-type BadInterfaceUsedInTests interface {
- ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
-}
-
// printf is used by the test.
func printf(format string, args ...interface{}) {
panic("don't call - testing only")
// checkField checks a struct field tag.
func (f *File) checkCanonicalFieldTag(field *ast.Field) {
+ if !*vetStructTags && !*vetAll {
+ return
+ }
if field.Tag == nil {
return
}
return
}
}
+
+type BadTypeUsedInTests struct {
+ X int "hello" // ERROR "struct field tag"
+}
// checkUntaggedLiteral checks if a composite literal is an struct literal with
// untagged fields.
func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
+ if !*vetUntaggedLiteral && !*vetAll {
+ return
+ }
// Check if the CompositeLit contains an untagged field.
allKeyValue := true
for _, e := range c.Elts {
"image.Point": true,
"image.Rectangle": true,
}
+
+type BadTag struct {
+ S string `this is a bad tag`
+}