Source file src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go
1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package printf defines an Analyzer that checks consistency 6 // of Printf format strings and arguments. 7 // 8 // # Analyzer printf 9 // 10 // printf: check consistency of Printf format strings and arguments 11 // 12 // The check applies to calls of the formatting functions such as 13 // [fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of 14 // those functions such as [log.Printf]. It reports a variety of 15 // mistakes such as syntax errors in the format string and mismatches 16 // (of number and type) between the verbs and their arguments. 17 // 18 // See the documentation of the fmt package for the complete set of 19 // format operators and their operand types. 20 // 21 // # Examples 22 // 23 // The %d format operator requires an integer operand. 24 // Here it is incorrectly applied to a string: 25 // 26 // fmt.Printf("%d", "hello") // fmt.Printf format %d has arg "hello" of wrong type string 27 // 28 // A call to Printf must have as many operands as there are "verbs" in 29 // the format string, not too few: 30 // 31 // fmt.Printf("%d") // fmt.Printf format reads arg 1, but call has 0 args 32 // 33 // nor too many: 34 // 35 // fmt.Printf("%d", 1, 2) // fmt.Printf call needs 1 arg, but has 2 args 36 // 37 // Explicit argument indexes must be no greater than the number of 38 // arguments: 39 // 40 // fmt.Printf("%[3]d", 1, 2) // fmt.Printf call has invalid argument index 3 41 // 42 // The checker also uses a heuristic to report calls to Print-like 43 // functions that appear to have been intended for their Printf-like 44 // counterpart: 45 // 46 // log.Print("%d", 123) // log.Print call has possible formatting directive %d 47 // 48 // Conversely, it also reports calls to Printf-like functions with a 49 // non-constant format string and no other arguments: 50 // 51 // fmt.Printf(message) // non-constant format string in call to fmt.Printf 52 // 53 // Such calls may have been intended for the function's Print-like 54 // counterpart: if the value of message happens to contain "%", 55 // misformatting will occur. In this case, the checker additionally 56 // suggests a fix to turn the call into: 57 // 58 // fmt.Printf("%s", message) 59 // 60 // The %w verb, as used in fmt.Errorf, should have an operand whose type 61 // implements error, not a pointer to a type that implements error. Using a 62 // pointer can result in surprising behavior when passing the resulting error to 63 // errors.Is and errors.As. In the example below, MyError implements error: 64 // 65 // // %w wants operand of error type MyError, not pointer type *MyError (defeats errors.Is) 66 // err := fmt.Errorf("%w", &MyError{Msg: "my error"}) 67 // 68 // This feature applies only to files using at least Go 1.27. 69 // 70 // # Inferred printf wrappers 71 // 72 // Functions that delegate their arguments to fmt.Printf are 73 // considered "printf wrappers"; calls to them are subject to the same 74 // checking. In this example, logf is a printf wrapper: 75 // 76 // func logf(level int, format string, args ...any) { 77 // if enabled(level) { 78 // log.Printf(format, args...) 79 // } 80 // } 81 // 82 // logf(3, "invalid request: %v") // logf format reads arg 1, but call has 0 args 83 // 84 // To enable printf checking on a function that is not found by this 85 // analyzer's heuristics (for example, because control is obscured by 86 // dynamic method calls), insert a bogus call: 87 // 88 // func MyPrintf(format string, args ...any) { 89 // if false { 90 // _ = fmt.Sprintf(format, args...) // enable printf checking 91 // } 92 // ... 93 // } 94 // 95 // A local function may also be inferred as a printf wrapper. If it 96 // is assigned to a variable, each call made through that variable will 97 // be checked just like a call to a function: 98 // 99 // logf := func(format string, args ...any) { 100 // message := fmt.Sprintf(format, args...) 101 // log.Printf("%s: %s", prefix, message) 102 // } 103 // logf("%s", 123) // logf format %s has arg 123 of wrong type int 104 // 105 // Interface methods may also be analyzed as printf wrappers, if 106 // within the interface's package there is an assignment from a 107 // implementation type whose corresponding method is a printf wrapper. 108 // 109 // For example, the var declaration below causes a *myLoggerImpl value 110 // to be assigned to a Logger variable: 111 // 112 // type Logger interface { 113 // Logf(format string, args ...any) 114 // } 115 // 116 // type myLoggerImpl struct{ ... } 117 // 118 // var _ Logger = (*myLoggerImpl)(nil) 119 // 120 // func (*myLoggerImpl) Logf(format string, args ...any) { 121 // println(fmt.Sprintf(format, args...)) 122 // } 123 // 124 // Since myLoggerImpl's Logf method is a printf wrapper, this 125 // establishes that Logger.Logf is a printf wrapper too, causing 126 // dynamic calls through the interface to be checked: 127 // 128 // func f(log Logger) { 129 // log.Logf("%s", 123) // Logger.Logf format %s has arg 123 of wrong type int 130 // } 131 // 132 // This feature applies only to interface methods declared in files 133 // using at least Go 1.26. 134 // 135 // # Specifying printf wrappers by flag 136 // 137 // The -funcs flag specifies a comma-separated list of names of 138 // additional known formatting functions or methods. (This legacy flag 139 // is rarely used due to the automatic inference described above.) 140 // 141 // If the name contains a period, it must denote a specific function 142 // using one of the following forms: 143 // 144 // dir/pkg.Function 145 // dir/pkg.Type.Method 146 // (*dir/pkg.Type).Method 147 // 148 // Otherwise the name is interpreted as a case-insensitive unqualified 149 // identifier such as "errorf". Either way, if a listed name ends in f, the 150 // function is assumed to be Printf-like, taking a format string before the 151 // argument list. Otherwise it is assumed to be Print-like, taking a list 152 // of arguments with no format string. 153 package printf 154