From 8a7e7fc366a96379563cf8babd66b00fee55df9b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 1 Sep 2025 22:09:11 +0200 Subject: [PATCH 1/9] format code with gofumpt Signed-off-by: Sebastiaan van Stijn --- bool_slice.go | 2 -- bool_slice_test.go | 1 - bytes.go | 6 ------ flag.go | 7 +++---- golangflag.go | 3 +-- ip_slice.go | 2 -- ip_slice_test.go | 4 ++-- ipnet_slice.go | 2 -- ipnet_slice_test.go | 4 ++-- string.go | 1 + string_slice.go | 28 ++++++++++++++++++++-------- text.go | 3 +-- text_test.go | 2 +- 13 files changed, 31 insertions(+), 34 deletions(-) diff --git a/bool_slice.go b/bool_slice.go index 3731370d..06e0f50e 100644 --- a/bool_slice.go +++ b/bool_slice.go @@ -22,7 +22,6 @@ func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue { // Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag. // If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended. func (s *boolSliceValue) Set(val string) error { - // remove all quote characters rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") @@ -60,7 +59,6 @@ func (s *boolSliceValue) Type() string { // String defines a "native" format for this boolean slice flag value. func (s *boolSliceValue) String() string { - boolStrSlice := make([]string, len(*s.value)) for i, b := range *s.value { boolStrSlice[i] = strconv.FormatBool(b) diff --git a/bool_slice_test.go b/bool_slice_test.go index 3c5a274f..e6873b75 100644 --- a/bool_slice_test.go +++ b/bool_slice_test.go @@ -184,7 +184,6 @@ func TestBSAsSliceValue(t *testing.T) { } func TestBSBadQuoting(t *testing.T) { - tests := []struct { Want []bool FlagArg []string diff --git a/bytes.go b/bytes.go index 67d53045..6856088a 100644 --- a/bytes.go +++ b/bytes.go @@ -18,7 +18,6 @@ func (bytesHex bytesHexValue) String() string { // Set implements pflag.Value.Set. func (bytesHex *bytesHexValue) Set(value string) error { bin, err := hex.DecodeString(strings.TrimSpace(value)) - if err != nil { return err } @@ -39,7 +38,6 @@ func newBytesHexValue(val []byte, p *[]byte) *bytesHexValue { } func bytesHexConv(sval string) (interface{}, error) { - bin, err := hex.DecodeString(sval) if err == nil { @@ -52,7 +50,6 @@ func bytesHexConv(sval string) (interface{}, error) { // GetBytesHex return the []byte value of a flag with the given name func (f *FlagSet) GetBytesHex(name string) ([]byte, error) { val, err := f.getFlagType(name, "bytesHex", bytesHexConv) - if err != nil { return []byte{}, err } @@ -119,7 +116,6 @@ func (bytesBase64 bytesBase64Value) String() string { // Set implements pflag.Value.Set. func (bytesBase64 *bytesBase64Value) Set(value string) error { bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value)) - if err != nil { return err } @@ -140,7 +136,6 @@ func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value { } func bytesBase64ValueConv(sval string) (interface{}, error) { - bin, err := base64.StdEncoding.DecodeString(sval) if err == nil { return bin, nil @@ -152,7 +147,6 @@ func bytesBase64ValueConv(sval string) (interface{}, error) { // GetBytesBase64 return the []byte value of a flag with the given name func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) { val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv) - if err != nil { return []byte{}, err } diff --git a/flag.go b/flag.go index e9ca46e2..7c2fe2dd 100644 --- a/flag.go +++ b/flag.go @@ -698,7 +698,6 @@ func wrap(i, w int, s string) string { } return r - } // FlagUsagesWrapped returns a string containing the usage information @@ -963,17 +962,17 @@ func (f *FlagSet) usage() { // --unknown arg ... (args will be arg ...) func stripUnknownFlagValue(args []string) []string { if len(args) == 0 { - //--unknown + // --unknown return args } first := args[0] if len(first) > 0 && first[0] == '-' { - //--unknown --next-flag ... + // --unknown --next-flag ... return args } - //--unknown arg ... (args will be arg ...) + // --unknown arg ... (args will be arg ...) if len(args) > 1 { return args[1:] } diff --git a/golangflag.go b/golangflag.go index e62eab53..a58d568b 100644 --- a/golangflag.go +++ b/golangflag.go @@ -78,7 +78,7 @@ func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { Usage: goflag.Usage, Value: wrapFlagValue(goflag.Value), // Looks like golang flags don't set DefValue correctly :-( - //DefValue: goflag.DefValue, + // DefValue: goflag.DefValue, DefValue: goflag.Value.String(), } // Ex: if the golang flag was -v, allow both -v and --v to work @@ -158,4 +158,3 @@ func ParseSkippedFlags(osArgs []string, goFlagSet *goflag.FlagSet) error { } return goFlagSet.Parse(skippedFlags) } - diff --git a/ip_slice.go b/ip_slice.go index 775faae4..23bc991d 100644 --- a/ip_slice.go +++ b/ip_slice.go @@ -23,7 +23,6 @@ func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue { // Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag. // If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended. func (s *ipSliceValue) Set(val string) error { - // remove all quote characters rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") @@ -61,7 +60,6 @@ func (s *ipSliceValue) Type() string { // String defines a "native" format for this net.IP slice flag value. func (s *ipSliceValue) String() string { - ipStrSlice := make([]string, len(*s.value)) for i, ip := range *s.value { ipStrSlice[i] = ip.String() diff --git a/ip_slice_test.go b/ip_slice_test.go index d1892768..366dc195 100644 --- a/ip_slice_test.go +++ b/ip_slice_test.go @@ -165,7 +165,6 @@ func TestIPSAsSliceValue(t *testing.T) { } func TestIPSBadQuoting(t *testing.T) { - tests := []struct { Want []net.IP FlagArg []string @@ -222,7 +221,8 @@ func TestIPSBadQuoting(t *testing.T) { }, FlagArg: []string{ `"2e5e:66b2:6441:848:5b74:76ea:574c:3a7b, 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b,2e5e:66b2:6441:848:5b74:76ea:574c:3a7b "`, - " 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"}, + " 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b", + }, }, } diff --git a/ipnet_slice.go b/ipnet_slice.go index c6e89da1..2f722c0c 100644 --- a/ipnet_slice.go +++ b/ipnet_slice.go @@ -23,7 +23,6 @@ func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue { // Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag. // If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended. func (s *ipNetSliceValue) Set(val string) error { - // remove all quote characters rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") @@ -61,7 +60,6 @@ func (s *ipNetSliceValue) Type() string { // String defines a "native" format for this net.IPNet slice flag value. func (s *ipNetSliceValue) String() string { - ipNetStrSlice := make([]string, len(*s.value)) for i, n := range *s.value { ipNetStrSlice[i] = n.String() diff --git a/ipnet_slice_test.go b/ipnet_slice_test.go index 11644c58..3b470889 100644 --- a/ipnet_slice_test.go +++ b/ipnet_slice_test.go @@ -159,7 +159,6 @@ func TestIPNetCalledTwice(t *testing.T) { } func TestIPNetBadQuoting(t *testing.T) { - tests := []struct { Want []net.IPNet FlagArg []string @@ -216,7 +215,8 @@ func TestIPNetBadQuoting(t *testing.T) { }, FlagArg: []string{ `"2e5e:66b2:6441:848:5b74:76ea:574c:3a7b/128, 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b/128,2e5e:66b2:6441:848:5b74:76ea:574c:3a7b/128 "`, - " 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b/128"}, + " 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b/128", + }, }, } diff --git a/string.go b/string.go index 04e0a26f..c96b8020 100644 --- a/string.go +++ b/string.go @@ -12,6 +12,7 @@ func (s *stringValue) Set(val string) error { *s = stringValue(val) return nil } + func (s *stringValue) Type() string { return "string" } diff --git a/string_slice.go b/string_slice.go index 3cb2e69d..d421887e 100644 --- a/string_slice.go +++ b/string_slice.go @@ -98,9 +98,12 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) { // The argument p points to a []string variable in which to store the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// +// --ss="v1,v2" --ss="v3" +// // will result in -// []string{"v1", "v2", "v3"} +// +// []string{"v1", "v2", "v3"} func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) { f.VarP(newStringSliceValue(value, p), name, "", usage) } @@ -114,9 +117,12 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s // The argument p points to a []string variable in which to store the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// +// --ss="v1,v2" --ss="v3" +// // will result in -// []string{"v1", "v2", "v3"} +// +// []string{"v1", "v2", "v3"} func StringSliceVar(p *[]string, name string, value []string, usage string) { CommandLine.VarP(newStringSliceValue(value, p), name, "", usage) } @@ -130,9 +136,12 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage // The return value is the address of a []string variable that stores the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// +// --ss="v1,v2" --ss="v3" +// // will result in -// []string{"v1", "v2", "v3"} +// +// []string{"v1", "v2", "v3"} func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { p := []string{} f.StringSliceVarP(&p, name, "", value, usage) @@ -150,9 +159,12 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str // The return value is the address of a []string variable that stores the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// +// --ss="v1,v2" --ss="v3" +// // will result in -// []string{"v1", "v2", "v3"} +// +// []string{"v1", "v2", "v3"} func StringSlice(name string, value []string, usage string) *[]string { return CommandLine.StringSliceP(name, "", value, usage) } diff --git a/text.go b/text.go index 886d5a3d..bb057ac3 100644 --- a/text.go +++ b/text.go @@ -42,8 +42,7 @@ func (v textValue) String() string { return "" } -//end of copy - +// end of copy func (v textValue) Type() string { return reflect.ValueOf(v.p).Type().Name() } diff --git a/text_test.go b/text_test.go index e60c136a..2889576a 100644 --- a/text_test.go +++ b/text_test.go @@ -20,7 +20,7 @@ func TestText(t *testing.T) { expected time.Time }{ {"2003-01-02T15:04:05Z", true, time.Date(2003, 1, 2, 15, 04, 05, 0, time.UTC)}, - {"2003-01-02 15:05:01", false, time.Time{}}, //negative case, invalid layout + {"2003-01-02 15:05:01", false, time.Time{}}, // negative case, invalid layout {"2024-11-22T03:01:02Z", true, time.Date(2024, 11, 22, 3, 1, 02, 0, time.UTC)}, {"2006-01-02T15:04:05+07:00", true, time.Date(2006, 1, 2, 15, 4, 5, 0, time.FixedZone("UTC+7", 7*60*60))}, } From f8b8d647a019e84a3744c4f89fffa2b43ec6ab10 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 1 Sep 2025 21:56:26 +0200 Subject: [PATCH 2/9] fix errcheck linting Some of these were a slightly false positive, because flagSet.parseLongArg uses a named output var which was already assigned to `err`, and `flagSet.fail()` returns the error-as is; https://github.com/spf13/pflag/blob/10438578954bba2527fe5cae3684d4532b064bbe/flag.go#L935-L942 flag.go:1033:9: Error return value of `f.fail` is not checked (errcheck) f.fail(err) ^ flag.go:1109:9: Error return value of `f.fail` is not checked (errcheck) f.fail(err) ^ This patch just re-assigns it to `err` to keep the linters happy. Many other unhandled errors were either "neglectable" (e.g. errors from `fmt.Printf`), and some unhandled errors would likely cause tests to fail later on, but it doesn't hurt to be explicit and to explicitly mark unhandled errors. Signed-off-by: Sebastiaan van Stijn --- bool_slice.go | 2 +- bytes.go | 4 +- errors_test.go | 4 +- flag.go | 38 +++++++++---------- flag_test.go | 94 ++++++++++++++++++++++++++++++---------------- golangflag_test.go | 2 +- ip_slice.go | 2 +- ipnet_slice.go | 2 +- 8 files changed, 88 insertions(+), 60 deletions(-) diff --git a/bool_slice.go b/bool_slice.go index 06e0f50e..58a788d2 100644 --- a/bool_slice.go +++ b/bool_slice.go @@ -27,7 +27,7 @@ func (s *boolSliceValue) Set(val string) error { // read flag arguments with CSV parser boolStrSlice, err := readAsCSV(rmQuote.Replace(val)) - if err != nil && err != io.EOF { + if err != nil && err != io.EOF { //nolint:errorlint // not using errors.Is for compatibility with go1.12 return err } diff --git a/bytes.go b/bytes.go index 6856088a..1c100848 100644 --- a/bytes.go +++ b/bytes.go @@ -44,7 +44,7 @@ func bytesHexConv(sval string) (interface{}, error) { return bin, nil } - return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err) + return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err.Error()) } // GetBytesHex return the []byte value of a flag with the given name @@ -141,7 +141,7 @@ func bytesBase64ValueConv(sval string) (interface{}, error) { return bin, nil } - return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err) + return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err.Error()) } // GetBytesBase64 return the []byte value of a flag with the given name diff --git a/errors_test.go b/errors_test.go index 7b4c7a4d..11012f8f 100644 --- a/errors_test.go +++ b/errors_test.go @@ -51,8 +51,8 @@ func TestInvalidValueError(t *testing.T) { if err.GetValue() != "foo" { t.Errorf("Expected GetValue to return %q, got %q", "foo", err.GetValue()) } - if err.Unwrap() != expectedCause { - t.Errorf("Expected Unwrwap to return %q, got %q", expectedCause, err.Unwrap()) + if actual := err.Unwrap(); actual != expectedCause { //nolint:errorlint // not using errors.Is for compatibility with go1.12 + t.Errorf("Expected Unwrwap to return %q, got %q", expectedCause, actual) } } diff --git a/flag.go b/flag.go index 7c2fe2dd..e92e2c16 100644 --- a/flag.go +++ b/flag.go @@ -388,7 +388,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag { } if len(name) > 1 { msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) - fmt.Fprintf(f.Output(), msg) + _, _ = fmt.Fprint(f.Output(), msg) panic(msg) } c := name[0] @@ -510,7 +510,7 @@ func (f *FlagSet) Set(name, value string) error { } if flag.Deprecated != "" { - fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + _, _ = fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) } return nil } @@ -551,7 +551,7 @@ func Set(name, value string) error { // otherwise, the default values of all defined flags in the set. func (f *FlagSet) PrintDefaults() { usages := f.FlagUsages() - fmt.Fprint(f.Output(), usages) + _, _ = fmt.Fprint(f.Output(), usages) } // defaultIsZeroValue returns true if the default value for this flag represents @@ -771,7 +771,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string { sidx := strings.Index(line, "\x00") spacing := strings.Repeat(" ", maxlen-sidx) // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx - fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) + _, _ = fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) } return buf.String() @@ -790,7 +790,7 @@ func PrintDefaults() { // defaultUsage is the default function to print a usage message. func defaultUsage(f *FlagSet) { - fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name) + _, _ = fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name) f.PrintDefaults() } @@ -803,7 +803,7 @@ func defaultUsage(f *FlagSet) { // By default it prints a simple header and calls PrintDefaults; for details about the // format of the output and how to control it, see the documentation for PrintDefaults. var Usage = func() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + _, _ = fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) PrintDefaults() } @@ -876,7 +876,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { _, alreadyThere := f.formal[normalizedFlagName] if alreadyThere { msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) - fmt.Fprintln(f.Output(), msg) + _, _ = fmt.Fprintln(f.Output(), msg) panic(msg) // Happens only if flags are declared with identical names } if f.formal == nil { @@ -892,7 +892,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { } if len(flag.Shorthand) > 1 { msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) - fmt.Fprintf(f.Output(), msg) + _, _ = fmt.Fprint(f.Output(), msg) panic(msg) } if f.shorthands == nil { @@ -902,7 +902,7 @@ func (f *FlagSet) AddFlag(flag *Flag) { used, alreadyThere := f.shorthands[c] if alreadyThere { msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) - fmt.Fprintf(f.Output(), msg) + _, _ = fmt.Fprint(f.Output(), msg) panic(msg) } f.shorthands[c] = flag @@ -1034,7 +1034,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin err = fn(flag, value) if err != nil { - f.fail(err) + err = f.fail(err) } return } @@ -1105,12 +1105,12 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse } if flag.ShorthandDeprecated != "" { - fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) + _, _ = fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) } err = fn(flag, value) if err != nil { - f.fail(err) + err = f.fail(err) } return } @@ -1168,7 +1168,7 @@ func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) { func (f *FlagSet) Parse(arguments []string) error { if f.addedGoFlagSets != nil { for _, goFlagSet := range f.addedGoFlagSets { - goFlagSet.Parse(nil) + _ = goFlagSet.Parse(nil) } } f.parsed = true @@ -1189,10 +1189,10 @@ func (f *FlagSet) Parse(arguments []string) error { case ContinueOnError: return err case ExitOnError: - if err == ErrHelp { + if err == ErrHelp { //nolint:errorlint // not using errors.Is for compatibility with go1.12 os.Exit(0) } - fmt.Fprintln(f.Output(), err) + _, _ = fmt.Fprintln(f.Output(), err) os.Exit(2) case PanicOnError: panic(err) @@ -1218,10 +1218,10 @@ func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) case ContinueOnError: return err case ExitOnError: - if err == ErrHelp { + if err == ErrHelp { //nolint:errorlint // not using errors.Is for compatibility with go1.12 os.Exit(0) } - fmt.Fprintln(f.Output(), err) + _, _ = fmt.Fprintln(f.Output(), err) os.Exit(2) case PanicOnError: panic(err) @@ -1239,7 +1239,7 @@ func (f *FlagSet) Parsed() bool { // after all flags are defined and before flags are accessed by the program. func Parse() { // Ignore errors; CommandLine is set for ExitOnError. - CommandLine.Parse(os.Args[1:]) + _ = CommandLine.Parse(os.Args[1:]) } // ParseAll parses the command-line flags from os.Args[1:] and called fn for each. @@ -1247,7 +1247,7 @@ func Parse() { // defined and before flags are accessed by the program. func ParseAll(fn func(flag *Flag, value string) error) { // Ignore errors; CommandLine is set for ExitOnError. - CommandLine.ParseAll(os.Args[1:], fn) + _ = CommandLine.ParseAll(os.Args[1:], fn) } // SetInterspersed sets whether to support interspersed option/non-option arguments. diff --git a/flag_test.go b/flag_test.go index c60e344b..07308594 100644 --- a/flag_test.go +++ b/flag_test.go @@ -20,15 +20,16 @@ import ( ) var ( - testBool = Bool("test_bool", false, "bool value") - testInt = Int("test_int", 0, "int value") - testInt64 = Int64("test_int64", 0, "int64 value") - testUint = Uint("test_uint", 0, "uint value") - testUint64 = Uint64("test_uint64", 0, "uint64 value") - testString = String("test_string", "0", "string value") - testFloat = Float64("test_float64", 0, "float64 value") - testDuration = Duration("test_duration", 0, "time.Duration value") - testOptionalInt = Int("test_optional_int", 0, "optional int value") + _ = Bool("test_bool", false, "bool value") + _ = Int("test_int", 0, "int value") + _ = Int64("test_int64", 0, "int64 value") + _ = Uint("test_uint", 0, "uint value") + _ = Uint64("test_uint64", 0, "uint64 value") + _ = String("test_string", "0", "string value") + _ = Float64("test_float64", 0, "float64 value") + _ = Duration("test_duration", 0, "time.Duration value") + _ = Int("test_optional_int", 0, "optional int value") + normalizeFlagNameInvocations = 0 ) @@ -75,15 +76,33 @@ func TestEverything(t *testing.T) { } } // Now set all flags - Set("test_bool", "true") - Set("test_int", "1") - Set("test_int64", "1") - Set("test_uint", "1") - Set("test_uint64", "1") - Set("test_string", "1") - Set("test_float64", "1") - Set("test_duration", "1s") - Set("test_optional_int", "1") + if err := Set("test_bool", "true"); err != nil { + t.Error(err) + } + if err := Set("test_int", "1"); err != nil { + t.Error(err) + } + if err := Set("test_int64", "1"); err != nil { + t.Error(err) + } + if err := Set("test_uint", "1"); err != nil { + t.Error(err) + } + if err := Set("test_uint64", "1"); err != nil { + t.Error(err) + } + if err := Set("test_string", "1"); err != nil { + t.Error(err) + } + if err := Set("test_float64", "1"); err != nil { + t.Error(err) + } + if err := Set("test_duration", "1s"); err != nil { + t.Error(err) + } + if err := Set("test_optional_int", "1"); err != nil { + t.Error(err) + } desired = "1" Visit(visitor) if len(m) != 9 { @@ -630,7 +649,7 @@ func TestShorthandLookup(t *testing.T) { t.Errorf("f.ShorthandLookup(\"\") did not return nil") } defer func() { - recover() + _ = recover() }() flag = f.ShorthandLookup("ab") // should NEVER get here. lookup should panic. defer'd func should recover it. @@ -906,7 +925,9 @@ func TestNormalizationSetFlags(t *testing.T) { } f.Bool(testName, false, "bool value") - f.Set(testName, "true") + if err := f.Set(testName, "true"); err != nil { + t.Error(err) + } f.SetNormalizeFunc(nfunc) if len(f.formal) != 1 { @@ -964,7 +985,12 @@ func TestSetOutput(t *testing.T) { var buf bytes.Buffer flags.SetOutput(&buf) flags.Init("test", ContinueOnError) - flags.Parse([]string{"--unknown"}) + + expectedErr := "unknown flag: --unknown" + err := flags.Parse([]string{"--unknown"}) + if err == nil || err.Error() != expectedErr { + t.Errorf("expected error %q got %v", expectedErr, err) + } if out := buf.String(); !strings.Contains(out, "--unknown") { t.Logf("expected output mentioning unknown; got %q", out) } @@ -975,7 +1001,7 @@ func TestOutput(t *testing.T) { var buf bytes.Buffer expect := "an example string" flags.SetOutput(&buf) - fmt.Fprint(flags.Output(), expect) + _, _ = fmt.Fprint(flags.Output(), expect) if out := buf.String(); !strings.Contains(out, expect) { t.Errorf("expected output %q; got %q", expect, out) } @@ -1027,7 +1053,7 @@ func TestHelp(t *testing.T) { if err == nil { t.Fatal("error expected") } - if err != ErrHelp { + if err != ErrHelp { //nolint:errorlint // not using errors.Is for compatibility with go1.12 t.Fatal("expected ErrHelp; got ", err) } if !helpCalled { @@ -1101,7 +1127,7 @@ func TestTermination(t *testing.T) { func getDeprecatedFlagSet() *FlagSet { f := NewFlagSet("bob", ContinueOnError) f.Bool("badflag", true, "always true") - f.MarkDeprecated("badflag", "use --good-flag instead") + _ = f.MarkDeprecated("badflag", "use --good-flag instead") return f } @@ -1142,7 +1168,7 @@ func TestDeprecatedFlagShorthandInDocs(t *testing.T) { f := NewFlagSet("bob", ContinueOnError) name := "noshorthandflag" f.BoolP(name, "n", true, "always true") - f.MarkShorthandDeprecated("noshorthandflag", fmt.Sprintf("use --%s instead", name)) + _ = f.MarkShorthandDeprecated("noshorthandflag", fmt.Sprintf("use --%s instead", name)) out := new(bytes.Buffer) f.SetOutput(out) @@ -1164,11 +1190,11 @@ func parseReturnStderr(t *testing.T, f *FlagSet, args []string) (string, error) // copy the output in a separate goroutine so printing can't block indefinitely go func() { var buf bytes.Buffer - io.Copy(&buf, r) + _, _ = io.Copy(&buf, r) outC <- buf.String() }() - w.Close() + _ = w.Close() os.Stderr = oldStderr out := <-outC @@ -1179,7 +1205,7 @@ func TestDeprecatedFlagUsage(t *testing.T) { f := NewFlagSet("bob", ContinueOnError) f.Bool("badflag", true, "always true") usageMsg := "use --good-flag instead" - f.MarkDeprecated("badflag", usageMsg) + _ = f.MarkDeprecated("badflag", usageMsg) args := []string{"--badflag"} out, err := parseReturnStderr(t, f, args) @@ -1197,7 +1223,7 @@ func TestDeprecatedFlagShorthandUsage(t *testing.T) { name := "noshorthandflag" f.BoolP(name, "n", true, "always true") usageMsg := fmt.Sprintf("use --%s instead", name) - f.MarkShorthandDeprecated(name, usageMsg) + _ = f.MarkShorthandDeprecated(name, usageMsg) args := []string{"-n"} out, err := parseReturnStderr(t, f, args) @@ -1215,7 +1241,7 @@ func TestDeprecatedFlagUsageNormalized(t *testing.T) { f.Bool("bad-double_flag", true, "always true") f.SetNormalizeFunc(wordSepNormalizeFunc) usageMsg := "use --good-flag instead" - f.MarkDeprecated("bad_double-flag", usageMsg) + _ = f.MarkDeprecated("bad_double-flag", usageMsg) args := []string{"--bad_double_flag"} out, err := parseReturnStderr(t, f, args) @@ -1244,7 +1270,7 @@ func TestMultipleNormalizeFlagNameInvocations(t *testing.T) { func TestHiddenFlagInUsage(t *testing.T) { f := NewFlagSet("bob", ContinueOnError) f.Bool("secretFlag", true, "shhh") - f.MarkHidden("secretFlag") + _ = f.MarkHidden("secretFlag") out := new(bytes.Buffer) f.SetOutput(out) @@ -1258,7 +1284,7 @@ func TestHiddenFlagInUsage(t *testing.T) { func TestHiddenFlagUsage(t *testing.T) { f := NewFlagSet("bob", ContinueOnError) f.Bool("secretFlag", true, "shhh") - f.MarkHidden("secretFlag") + _ = f.MarkHidden("secretFlag") args := []string{"--secretFlag"} out, err := parseReturnStderr(t, f, args) @@ -1384,7 +1410,9 @@ func TestVisitFlagOrder(t *testing.T) { names := []string{"C", "B", "A", "D"} for _, name := range names { fs.Bool(name, false, "") - fs.Set(name, "true") + if err := fs.Set(name, "true"); err != nil { + t.Error(err) + } } i := 0 diff --git a/golangflag_test.go b/golangflag_test.go index 7309808d..9ef6494a 100644 --- a/golangflag_test.go +++ b/golangflag_test.go @@ -74,7 +74,7 @@ func TestToGoflags(t *testing.T) { pfs.Duration("DurationFlag", time.Second, "Duration flag usage") pfs.Bool("BoolFlag", true, "Bool flag usage") pfs.String("deprecated", "Deprecated value", "Deprecated flag usage") - pfs.MarkDeprecated("deprecated", "obsolete") + _ = pfs.MarkDeprecated("deprecated", "obsolete") pfs.CopyToGoFlagSet(&gfs) diff --git a/ip_slice.go b/ip_slice.go index 23bc991d..12ab6524 100644 --- a/ip_slice.go +++ b/ip_slice.go @@ -28,7 +28,7 @@ func (s *ipSliceValue) Set(val string) error { // read flag arguments with CSV parser ipStrSlice, err := readAsCSV(rmQuote.Replace(val)) - if err != nil && err != io.EOF { + if err != nil && err != io.EOF { //nolint:errorlint // not using errors.Is for compatibility with go1.12 return err } diff --git a/ipnet_slice.go b/ipnet_slice.go index 2f722c0c..c051fbd2 100644 --- a/ipnet_slice.go +++ b/ipnet_slice.go @@ -28,7 +28,7 @@ func (s *ipNetSliceValue) Set(val string) error { // read flag arguments with CSV parser ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val)) - if err != nil && err != io.EOF { + if err != nil && err != io.EOF { //nolint:errorlint // not using errors.Is for compatibility with go1.12 return err } From c10337f4f02abf35fe19a5bf784a3c8984f1ea5b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 1 Sep 2025 22:21:18 +0200 Subject: [PATCH 3/9] fix staticcheck linting duration_slice.go:49:12: S1025: should use String() instead of fmt.Sprintf (staticcheck) out[i] = fmt.Sprintf("%s", d) ^ duration_slice.go:59:9: S1025: should use String() instead of fmt.Sprintf (staticcheck) return fmt.Sprintf("%s", val) ^ flag.go:658:10: QF1004: could use strings.ReplaceAll instead (staticcheck) return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1) ^ flag.go:676:10: QF1004: could use strings.ReplaceAll instead (staticcheck) return strings.Replace(s, "\n", r, -1) ^ flag.go:688:10: QF1004: could use strings.ReplaceAll instead (staticcheck) r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1) ^ flag_test.go:641:5: SA5011(related information): this check suggests that the pointer can be nil (staticcheck) if flag == nil { ^ flag_test.go:644:10: SA5011: possible nil pointer dereference (staticcheck) if flag.Name != "boola" { ^ flag_test.go:654:2: SA4006: this value of flag is never used (staticcheck) flag = f.ShorthandLookup("ab") ^ ipnet_slice_test.go:16:2: S1008: should use 'return c1.String() == c2.String()' instead of 'if c1.String() == c2.String() { return true }; return false' (staticcheck) if c1.String() == c2.String() { ^ string_array.go:33:2: S1001: should use copy(to, from) instead of a loop (staticcheck) for i, d := range val { ^ string_array.go:42:2: S1001: should use copy(to, from) instead of a loop (staticcheck) for i, d := range *s.value { ^ flag.go:658:10: QF1004: could use strings.ReplaceAll instead (staticcheck) return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1) ^ flag.go:676:10: QF1004: could use strings.ReplaceAll instead (staticcheck) return strings.Replace(s, "\n", r, -1) ^ flag_test.go:757:12: QF1004: could use strings.ReplaceAll instead (staticcheck) result = strings.Replace(result, sep, to, -1) ^ flag_test.go:757:12: QF1004: could use strings.ReplaceAll instead (staticcheck) result = strings.Replace(result, sep, to, -1) ^ Signed-off-by: Sebastiaan van Stijn --- duration_slice.go | 5 ++--- flag.go | 8 ++++---- flag_test.go | 6 +++--- ipnet_slice_test.go | 5 +---- string_array.go | 8 ++------ 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/duration_slice.go b/duration_slice.go index badadda5..ee987274 100644 --- a/duration_slice.go +++ b/duration_slice.go @@ -1,7 +1,6 @@ package pflag import ( - "fmt" "strings" "time" ) @@ -46,7 +45,7 @@ func (s *durationSliceValue) Type() string { func (s *durationSliceValue) String() string { out := make([]string, len(*s.value)) for i, d := range *s.value { - out[i] = fmt.Sprintf("%s", d) + out[i] = d.String() } return "[" + strings.Join(out, ",") + "]" } @@ -56,7 +55,7 @@ func (s *durationSliceValue) fromString(val string) (time.Duration, error) { } func (s *durationSliceValue) toString(val time.Duration) string { - return fmt.Sprintf("%s", val) + return val.String() } func (s *durationSliceValue) Append(val string) error { diff --git a/flag.go b/flag.go index e92e2c16..c1639a44 100644 --- a/flag.go +++ b/flag.go @@ -657,7 +657,7 @@ func wrapN(i, slop int, s string) (string, string) { // caller). Pass `w` == 0 to do no wrapping func wrap(i, w int, s string) string { if w == 0 { - return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1) + return strings.ReplaceAll(s, "\n", "\n"+strings.Repeat(" ", i)) } // space between indent i and end of line width w into which @@ -675,7 +675,7 @@ func wrap(i, w int, s string) string { } // If still not enough space then don't even try to wrap. if wrap < 24 { - return strings.Replace(s, "\n", r, -1) + return strings.ReplaceAll(s, "\n", r) } // Try to avoid short orphan words on the final line, by @@ -687,14 +687,14 @@ func wrap(i, w int, s string) string { // Handle first line, which is indented by the caller (or the // special case above) l, s = wrapN(wrap, slop, s) - r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1) + r = r + strings.ReplaceAll(l, "\n", "\n"+strings.Repeat(" ", i)) // Now wrap the rest for s != "" { var t string t, s = wrapN(wrap, slop, s) - r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1) + r = r + "\n" + strings.Repeat(" ", i) + strings.ReplaceAll(t, "\n", "\n"+strings.Repeat(" ", i)) } return r diff --git a/flag_test.go b/flag_test.go index 07308594..fa982572 100644 --- a/flag_test.go +++ b/flag_test.go @@ -639,7 +639,7 @@ func TestShorthandLookup(t *testing.T) { } flag := f.ShorthandLookup("a") if flag == nil { - t.Errorf("f.ShorthandLookup(\"a\") returned nil") + t.Fatal("f.ShorthandLookup(\"a\") returned nil") } if flag.Name != "boola" { t.Errorf("f.ShorthandLookup(\"a\") found %q instead of \"boola\"", flag.Name) @@ -651,7 +651,7 @@ func TestShorthandLookup(t *testing.T) { defer func() { _ = recover() }() - flag = f.ShorthandLookup("ab") + _ = f.ShorthandLookup("ab") // should NEVER get here. lookup should panic. defer'd func should recover it. t.Errorf("f.ShorthandLookup(\"ab\") did not panic") } @@ -754,7 +754,7 @@ func TestChangedHelper(t *testing.T) { func replaceSeparators(name string, from []string, to string) string { result := name for _, sep := range from { - result = strings.Replace(result, sep, to, -1) + result = strings.ReplaceAll(result, sep, to) } // Type convert to indicate normalization has been done. return result diff --git a/ipnet_slice_test.go b/ipnet_slice_test.go index 3b470889..d6bab653 100644 --- a/ipnet_slice_test.go +++ b/ipnet_slice_test.go @@ -13,10 +13,7 @@ func getCIDR(ip net.IP, cidr *net.IPNet, err error) net.IPNet { } func equalCIDR(c1 net.IPNet, c2 net.IPNet) bool { - if c1.String() == c2.String() { - return true - } - return false + return c1.String() == c2.String() } func setUpIPNetFlagSet(ipsp *[]net.IPNet) *FlagSet { diff --git a/string_array.go b/string_array.go index d1ff0a96..2404407f 100644 --- a/string_array.go +++ b/string_array.go @@ -30,18 +30,14 @@ func (s *stringArrayValue) Append(val string) error { func (s *stringArrayValue) Replace(val []string) error { out := make([]string, len(val)) - for i, d := range val { - out[i] = d - } + copy(out, val) *s.value = out return nil } func (s *stringArrayValue) GetSlice() []string { out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = d - } + copy(out, *s.value) return out } From 56f2642d9772bfa39771e9673722ed84b73ffc0f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 1 Sep 2025 22:25:25 +0200 Subject: [PATCH 4/9] fix unconvert linting bool_test.go:29:22: unnecessary conversion (unconvert) return triStateValue(*v) ^ count.go:16:18: unnecessary conversion (unconvert) *i = countValue(*i + 1) ^ uint64.go:30:15: unnecessary conversion (unconvert) return uint64(v), nil ^ Signed-off-by: Sebastiaan van Stijn --- bool_test.go | 2 +- count.go | 2 +- uint64.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bool_test.go b/bool_test.go index a4319e79..e3704fcd 100644 --- a/bool_test.go +++ b/bool_test.go @@ -26,7 +26,7 @@ func (v *triStateValue) IsBoolFlag() bool { } func (v *triStateValue) Get() interface{} { - return triStateValue(*v) + return *v } func (v *triStateValue) Set(s string) error { diff --git a/count.go b/count.go index d49c0143..521b5d21 100644 --- a/count.go +++ b/count.go @@ -13,7 +13,7 @@ func newCountValue(val int, p *int) *countValue { func (i *countValue) Set(s string) error { // "+1" means that no specific value was passed, so increment if s == "+1" { - *i = countValue(*i + 1) + *i = *i + 1 return nil } v, err := strconv.ParseInt(s, 0, 0) diff --git a/uint64.go b/uint64.go index f62240f2..86d8c7e6 100644 --- a/uint64.go +++ b/uint64.go @@ -27,7 +27,7 @@ func uint64Conv(sval string) (interface{}, error) { if err != nil { return 0, err } - return uint64(v), nil + return v, nil } // GetUint64 return the uint64 value of a flag with the given name From e1dfb8fd715efaee0fb06197b1d1b6b904d54797 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 1 Sep 2025 22:31:59 +0200 Subject: [PATCH 5/9] fix unparam linting flag_test.go:754:52: replaceSeparators - to always receives "." (unparam) func replaceSeparators(name string, from []string, to string) string { ^ flag_test.go:1182:24: parseReturnStderr - t is unused (unparam) func parseReturnStderr(t *testing.T, f *FlagSet, args []string) (string, error) { ^ ip_slice.go:73:56: (*ipSliceValue).fromString - result 1 (error) is always nil (unparam) func (s *ipSliceValue) fromString(val string) (net.IP, error) { ^ Signed-off-by: Sebastiaan van Stijn --- flag_test.go | 13 +++++++------ ip_slice.go | 16 ++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/flag_test.go b/flag_test.go index fa982572..420c2ab1 100644 --- a/flag_test.go +++ b/flag_test.go @@ -751,10 +751,10 @@ func TestChangedHelper(t *testing.T) { } } -func replaceSeparators(name string, from []string, to string) string { +func toDotSeparated(name string, from []string) string { result := name for _, sep := range from { - result = strings.ReplaceAll(result, sep, to) + result = strings.ReplaceAll(result, sep, ".") } // Type convert to indicate normalization has been done. return result @@ -762,7 +762,7 @@ func replaceSeparators(name string, from []string, to string) string { func wordSepNormalizeFunc(f *FlagSet, name string) NormalizedName { seps := []string{"-", "_"} - name = replaceSeparators(name, seps, ".") + name = toDotSeparated(name, seps) normalizeFlagNameInvocations++ return NormalizedName(name) @@ -821,10 +821,10 @@ func TestWordSepNormalizedNames(t *testing.T) { func aliasAndWordSepFlagNames(f *FlagSet, name string) NormalizedName { seps := []string{"-", "_"} - oldName := replaceSeparators("old-valid_flag", seps, ".") - newName := replaceSeparators("valid-flag", seps, ".") + oldName := toDotSeparated("old-valid_flag", seps) + newName := toDotSeparated("valid-flag", seps) - name = replaceSeparators(name, seps, ".") + name = toDotSeparated(name, seps) switch name { case oldName: name = newName @@ -1180,6 +1180,7 @@ func TestDeprecatedFlagShorthandInDocs(t *testing.T) { } func parseReturnStderr(t *testing.T, f *FlagSet, args []string) (string, error) { + t.Helper() oldStderr := os.Stderr r, w, _ := os.Pipe() os.Stderr = w diff --git a/ip_slice.go b/ip_slice.go index 12ab6524..84fa4189 100644 --- a/ip_slice.go +++ b/ip_slice.go @@ -70,8 +70,8 @@ func (s *ipSliceValue) String() string { return "[" + out + "]" } -func (s *ipSliceValue) fromString(val string) (net.IP, error) { - return net.ParseIP(strings.TrimSpace(val)), nil +func (s *ipSliceValue) fromString(val string) net.IP { + return net.ParseIP(strings.TrimSpace(val)) } func (s *ipSliceValue) toString(val net.IP) string { @@ -79,22 +79,14 @@ func (s *ipSliceValue) toString(val net.IP) string { } func (s *ipSliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) + *s.value = append(*s.value, s.fromString(val)) return nil } func (s *ipSliceValue) Replace(val []string) error { out := make([]net.IP, len(val)) for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } + out[i] = s.fromString(d) } *s.value = out return nil From 5565589c12b2a4114b810af2700bb30d7e40fc30 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 1 Sep 2025 22:38:39 +0200 Subject: [PATCH 6/9] fix revive linting bool_func_test.go:53:48: unused-parameter: parameter 's' seems to be unused, consider removing or renaming it as _ (revive) fset.BoolFunc("flag1", "usage message", func(s string) error { return nil }) ^ bool_func_test.go:67:72: unused-parameter: parameter 's' seems to be unused, consider removing or renaming it as _ (revive) fset.BoolFunc("flag2", "usage message with `name` placeholder", func(s string) error { return nil }) ^ flag_test.go:763:27: unused-parameter: parameter 'f' seems to be unused, consider removing or renaming it as _ (revive) func wordSepNormalizeFunc(f *FlagSet, name string) NormalizedName { ^ flag_test.go:821:31: unused-parameter: parameter 'f' seems to be unused, consider removing or renaming it as _ (revive) func aliasAndWordSepFlagNames(f *FlagSet, name string) NormalizedName { ^ flag_test.go:1390:27: unused-parameter: parameter 'f' seems to be unused, consider removing or renaming it as _ (revive) fs.SetNormalizeFunc(func(f *FlagSet, name string) NormalizedName { ^ func_test.go:67:44: unused-parameter: parameter 's' seems to be unused, consider removing or renaming it as _ (revive) fset.Func("flag1", "usage message", func(s string) error { return nil }) ^ golangflag.go:74:6: exported: func name will be used as pflag.PFlagFromGoFlag by other packages, and that stutters; consider calling this FromGoFlag (revive) func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { ^ ipnet_slice_test.go:11:14: unused-parameter: parameter 'ip' seems to be unused, consider removing or renaming it as _ (revive) func getCIDR(ip net.IP, cidr *net.IPNet, err error) net.IPNet { ^ time.go:54:9: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive) } else { return d.Time.Format(time.RFC3339Nano) } Signed-off-by: Sebastiaan van Stijn --- bool_func_test.go | 4 ++-- flag.go | 2 +- flag_test.go | 6 +++--- func_test.go | 4 ++-- golangflag.go | 2 +- ipnet_slice_test.go | 2 +- time.go | 3 +-- 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/bool_func_test.go b/bool_func_test.go index 765c9c08..672d23a7 100644 --- a/bool_func_test.go +++ b/bool_func_test.go @@ -50,7 +50,7 @@ func TestBoolFuncUsage(t *testing.T) { // regular boolfunc flag: // expect to see '--flag1' followed by the usageMessage, and no mention of a default value fset := NewFlagSet("unittest", ContinueOnError) - fset.BoolFunc("flag1", "usage message", func(s string) error { return nil }) + fset.BoolFunc("flag1", "usage message", func(string) error { return nil }) usage := fset.FlagUsagesWrapped(80) usage = strings.TrimSpace(usage) @@ -64,7 +64,7 @@ func TestBoolFuncUsage(t *testing.T) { // func flag, with a placeholder name: // if usageMesage contains a placeholder, expect '--flag2 {placeholder}'; still expect no mention of a default value fset := NewFlagSet("unittest", ContinueOnError) - fset.BoolFunc("flag2", "usage message with `name` placeholder", func(s string) error { return nil }) + fset.BoolFunc("flag2", "usage message with `name` placeholder", func(string) error { return nil }) usage := fset.FlagUsagesWrapped(80) usage = strings.TrimSpace(usage) diff --git a/flag.go b/flag.go index c1639a44..a041a15d 100644 --- a/flag.go +++ b/flag.go @@ -270,7 +270,7 @@ func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedNam if f.normalizeNameFunc != nil { return f.normalizeNameFunc } - return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) } + return func(_ *FlagSet, name string) NormalizedName { return NormalizedName(name) } } func (f *FlagSet) normalizeFlagName(name string) NormalizedName { diff --git a/flag_test.go b/flag_test.go index 420c2ab1..b367f7d2 100644 --- a/flag_test.go +++ b/flag_test.go @@ -760,7 +760,7 @@ func toDotSeparated(name string, from []string) string { return result } -func wordSepNormalizeFunc(f *FlagSet, name string) NormalizedName { +func wordSepNormalizeFunc(_ *FlagSet, name string) NormalizedName { seps := []string{"-", "_"} name = toDotSeparated(name, seps) normalizeFlagNameInvocations++ @@ -818,7 +818,7 @@ func TestWordSepNormalizedNames(t *testing.T) { testWordSepNormalizedNames(args, t) } -func aliasAndWordSepFlagNames(f *FlagSet, name string) NormalizedName { +func aliasAndWordSepFlagNames(_ *FlagSet, name string) NormalizedName { seps := []string{"-", "_"} oldName := toDotSeparated("old-valid_flag", seps) @@ -1387,7 +1387,7 @@ func TestVisitAllFlagOrder(t *testing.T) { fs := NewFlagSet("TestVisitAllFlagOrder", ContinueOnError) fs.SortFlags = false // https://github.com/spf13/pflag/issues/120 - fs.SetNormalizeFunc(func(f *FlagSet, name string) NormalizedName { + fs.SetNormalizeFunc(func(_ *FlagSet, name string) NormalizedName { return NormalizedName(name) }) diff --git a/func_test.go b/func_test.go index 4badf936..212b1375 100644 --- a/func_test.go +++ b/func_test.go @@ -64,7 +64,7 @@ func TestFuncUsage(t *testing.T) { // regular func flag: // expect to see '--flag1 value' followed by the usageMessage, and no mention of a default value fset := NewFlagSet("unittest", ContinueOnError) - fset.Func("flag1", "usage message", func(s string) error { return nil }) + fset.Func("flag1", "usage message", func(string) error { return nil }) usage := fset.FlagUsagesWrapped(80) usage = strings.TrimSpace(usage) @@ -78,7 +78,7 @@ func TestFuncUsage(t *testing.T) { // func flag, with a placeholder name: // if usageMesage contains a placeholder, expect that name; still expect no mention of a default value fset := NewFlagSet("unittest", ContinueOnError) - fset.Func("flag2", "usage message with `name` placeholder", func(s string) error { return nil }) + fset.Func("flag2", "usage message with `name` placeholder", func(string) error { return nil }) usage := fset.FlagUsagesWrapped(80) usage = strings.TrimSpace(usage) diff --git a/golangflag.go b/golangflag.go index a58d568b..88a5c499 100644 --- a/golangflag.go +++ b/golangflag.go @@ -71,7 +71,7 @@ func (v *flagValueWrapper) Type() string { // If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei // with both `-v` and `--v` in flags. If the golang flag was more than a single // character (ex: `verbose`) it will only be accessible via `--verbose` -func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { +func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { //nolint:revive // ignore "func name will be used as pflag.PFlagFromGoFlag by other packages, and that stutters" // Remember the default value as a string; it won't change. flag := &Flag{ Name: goflag.Name, diff --git a/ipnet_slice_test.go b/ipnet_slice_test.go index d6bab653..5ac387da 100644 --- a/ipnet_slice_test.go +++ b/ipnet_slice_test.go @@ -8,7 +8,7 @@ import ( ) // Helper function to set static slices -func getCIDR(ip net.IP, cidr *net.IPNet, err error) net.IPNet { +func getCIDR(_ net.IP, cidr *net.IPNet, _ error) net.IPNet { return *cidr } diff --git a/time.go b/time.go index 3dee4247..fe457dea 100644 --- a/time.go +++ b/time.go @@ -51,9 +51,8 @@ func (d *timeValue) Type() string { func (d *timeValue) String() string { if d.Time.IsZero() { return "" - } else { - return d.Time.Format(time.RFC3339Nano) } + return d.Time.Format(time.RFC3339Nano) } // GetTime return the time value of a flag with the given name From 1cdeda513b61627e9498b853391e2cd8c7ac84bf Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 18 Dec 2025 12:58:17 +0100 Subject: [PATCH 7/9] fix godoc for InvalidSyntaxError.GetSpecifiedFlag Signed-off-by: Sebastiaan van Stijn --- errors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/errors.go b/errors.go index ff11b66b..9bfa433a 100644 --- a/errors.go +++ b/errors.go @@ -142,7 +142,7 @@ func (e *InvalidSyntaxError) Error() string { return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag) } -// GetSpecifiedName returns the exact flag (with dashes) as it +// GetSpecifiedFlag returns the exact flag (with dashes) as it // appeared in the parsed arguments. func (e *InvalidSyntaxError) GetSpecifiedFlag() string { return e.specifiedFlag From 09b99402f8e827109814027b14e43cd4144690e6 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 1 Sep 2025 22:47:12 +0200 Subject: [PATCH 8/9] gha: update checkout v6.0.1, setup-go v6.1.0, golangci-lint v9.2.0 Signed-off-by: Sebastiaan van Stijn --- .github/workflows/ci.yaml | 12 ++++++------ .golangci.yaml | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7adfc939..e7a9d36f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,10 +17,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version: ${{ matrix.go }} @@ -35,14 +35,14 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Set up Go - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: go-version: "1.23" - name: Lint - uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 with: - version: v1.63.4 + version: v2.7 diff --git a/.golangci.yaml b/.golangci.yaml index b274f248..94ce2e02 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,4 +1,21 @@ +version: "2" + linters: - disable-all: true enable: + - errorlint - nolintlint + - revive + - unconvert + - unparam + settings: + staticcheck: + # Enable all options, with some exceptions. + # For defaults, see https://golangci-lint.run/usage/linters/#staticcheck + checks: + - all + - -QF1008 # Omit embedded fields from selector expression; https://staticcheck.dev/docs/checks/#QF1008 + - -ST1003 # Poorly chosen identifier; https://staticcheck.dev/docs/checks/#ST1003 + +formatters: + enable: + - gofmt From 9f0099236fd5d9d36da78abf37db055093bc2b30 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 2 Sep 2025 10:09:48 +0200 Subject: [PATCH 9/9] gha: tweak settings, add testing for "stable" and "oldstable" go - set default permissions to "content: read" as actions in this repository don't require write acccess. - set a guardrails timeout; this should not be needed normally, but GitHub's default timeout is 6 Hours, and prevents runaway actions that may happen occasionally on GitHub service outages. - remove filter for branch name and run on pull-requests, push events - add "stable" and "oldstable" Go versions to the matrix; these always point to the currently maintained versions of Go (currently Go1.25 and Go1.24). Using the fixed ("oldstable", "stable") keywords reduces maintainance and helps marking checks as "required" in branch protection, as such options are using the name generated from the matrix. Signed-off-by: Sebastiaan van Stijn --- .github/workflows/ci.yaml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e7a9d36f..18f44259 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,19 +1,24 @@ name: CI -on: - push: - branches: [master] - pull_request: +on: [push, pull_request] + +# Default to 'contents: read', which grants actions to read commits. Any +# permission not included is implicitly set to "none". +# +# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions +permissions: + contents: read jobs: test: name: Test runs-on: ubuntu-latest + timeout-minutes: 20 # guardrails timeout strategy: fail-fast: false matrix: - go: ["1.12", "1.21", "1.22", "1.23"] + go: ["1.12", "1.21", "1.22", "1.23", "oldstable", "stable"] steps: - name: Checkout repository @@ -32,6 +37,7 @@ jobs: lint: name: Lint runs-on: ubuntu-latest + timeout-minutes: 20 # guardrails timeout steps: - name: Checkout repository @@ -40,7 +46,7 @@ jobs: - name: Set up Go uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 with: - go-version: "1.23" + go-version: "stable" - name: Lint uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0