Goals
Add support for printf (and errorf) for function pointers and interfaces:
func Infof(string, any...)
func Errorf(string, any...)
func NewLogger() func(string, any...) {}
func SetLogger(func(string, any...))
type Logger interface {
Infof(string, any...)
}
var infof func(string, any...)
Why change is needed
Currently the implementation does work by (a) having either functions mapping a specified list (which can be provided to vet via commandline argument) or by (b) calling the fmt.Printf or fmt.Print function.
a) Providing a specific function mapping does not work with modules that are not imported within the source file. Also there is no config file which could be use provide this list project-wide or inherit it from imported modules. For the full mapping list, see here.
b) Calling the fmt.Printf or fmt.Print function directly does not work for arguments, return values, and interfaces.
c) Also IDEs like VS Code and Goland add support for vet-based rules. Adding this feature to vet will likely also trigger changes in the IDE support.
For more details on the implementation, see here.
Solutions
There are different ways to solve this issue. I would like to brainstorm different ways, so please feel free to add proposals in the comments.
I) Named Arguments and Return Values
Use named arguments and return values by either using printfFormat or errorfFormat as argument name:
func Infof(printfFormat string, any...)
func Errorf(errorfFormat string, any...)
func NewLogger() func(printfFormat string, any...) {}
func SetLogger(func(printfFormat string, any...))
type Logger interface {
Infof(printfFormat string, any...)
}
var infof func(printfFormat string, any...)
Pros: Easy to use, unlikely to cause side effects with existing code, clean upgrade path for existing modules, does not increase required Go version
Cons: Bloated code, argument names where non should be required
II) Add new fmt.FormatString and errors.FormatString
Add new fmt.FormatString and errors.FormatString types (which point to string) to declare the functions/methods as formatted:
func Infof(fmt.FormatString, any...)
func Errorf(errors.FormatString, any...)
func NewLogger() func(fmt.FormatString, any...) {}
func SetLogger(func(fmt.FormatString, any...))
type Logger interface {
Infof(fmt.FormatString, any...)
}
var infof func(fmt.FormatString, any...)
Pros: Safe from side effects with existing code
Cons: Impact on reflection, requires build tag on upgrading code, requires addition to core packages, requires upgrade to higer Go version
III) Add declaration list to go.mod
Allow additional printf-like functions to be declared within the go.mod file and have those settings inherited from imported modules. Package names are resolved relative to the module root.
module hello/world
go 1.21
vet printf logging.Infof
vet errorf logging.Errorf
vet printf logging.InfofFunc
Examples:
package logging
func Infof(string, any...)
func Errorf(string, any...)
type InfofFunc func(string, any...)
func NewLogger() InfofFunc {}
func SetLogger(InfofFunc)
type Logger interface {
Infof(string, any...)
}
var infof InfofFunc
Pros: no side effects on existing code
Cons: requires upgrade to higher Go version
IV) Add new go.vet config file
Allow additional printf-like functions to be declared within a new go.vet file and have those settings inherited from imported modules. Package names are resolved relative to the module root. (Similar to III but with less issues.)
The file should always be backward compatible and unknown and illegal entries should be ignored with a warning.
printf (
logging.Infof
logging.InfofFunc
)
errorf logging.Errorf
Pros: no side effects on existing code, clean upgrade path for existing modules, does not increase required Go version, could be used for additional go tool vet settings
Cons: new file added to Go universe
Please let me know what you think.
Best Regards, Felix
Goals
Add support for
printf(anderrorf) for function pointers and interfaces:Why change is needed
Currently the implementation does work by (a) having either functions mapping a specified list (which can be provided to
vetvia commandline argument) or by (b) calling thefmt.Printforfmt.Printfunction.a) Providing a specific function mapping does not work with modules that are not imported within the source file. Also there is no config file which could be use provide this list project-wide or inherit it from imported modules. For the full mapping list, see here.
b) Calling the
fmt.Printforfmt.Printfunction directly does not work for arguments, return values, and interfaces.c) Also IDEs like VS Code and Goland add support for
vet-based rules. Adding this feature tovetwill likely also trigger changes in the IDE support.For more details on the implementation, see here.
Solutions
There are different ways to solve this issue. I would like to brainstorm different ways, so please feel free to add proposals in the comments.
I) Named Arguments and Return Values
Use named arguments and return values by either using
printfFormatorerrorfFormatas argument name:Pros: Easy to use, unlikely to cause side effects with existing code, clean upgrade path for existing modules, does not increase required Go version
Cons: Bloated code, argument names where non should be required
II) Add new
fmt.FormatStringanderrors.FormatStringAdd new
fmt.FormatStringanderrors.FormatStringtypes (which point tostring) to declare the functions/methods as formatted:Pros: Safe from side effects with existing code
Cons: Impact on reflection, requires build tag on upgrading code, requires addition to core packages, requires upgrade to higer Go version
III) Add declaration list to
go.modAllow additional printf-like functions to be declared within the
go.modfile and have those settings inherited from imported modules. Package names are resolved relative to the module root.Examples:
Pros: no side effects on existing code
Cons: requires upgrade to higher Go version
IV) Add new
go.vetconfig fileAllow additional printf-like functions to be declared within a new
go.vetfile and have those settings inherited from imported modules. Package names are resolved relative to the module root. (Similar to III but with less issues.)The file should always be backward compatible and unknown and illegal entries should be ignored with a warning.
Pros: no side effects on existing code, clean upgrade path for existing modules, does not increase required Go version, could be used for additional
go tool vetsettingsCons: new file added to Go universe
Please let me know what you think.
Best Regards, Felix