From 3ab834d232d21286e5f725612febfb386f5a3e32 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 10 Apr 2026 11:42:00 -0700 Subject: [PATCH 1/3] size_test.go: replace interface{} with any The new keyword, any, is added to Go 1.18 for the sake of readability. It is an alias to interface{}. Signed-off-by: Kir Kolyshkin --- size_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/size_test.go b/size_test.go index 463f569..a8b40cb 100644 --- a/size_test.go +++ b/size_test.go @@ -256,7 +256,7 @@ func BenchmarkParseSize(b *testing.B) { } } -func assertEquals(t *testing.T, expected, actual interface{}) { +func assertEquals(t *testing.T, expected, actual any) { t.Helper() if expected != actual { t.Errorf("Expected '%v' but got '%v'", expected, actual) From 19cc109093498e90ae4b22b7180ee42e49825309 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 10 Apr 2026 11:52:47 -0700 Subject: [PATCH 2/3] ulimit.go: use strings.Cut Now when we have Go 1.20 we can finally switch from strings.Split[N] to strings.Cut. The code is easier and more readable, and we no longer deal with slices. There is a slight difference in behavior -- the old code was giving hints when an extra = or : was there. The new code just returns NumError. To me this is not a big deal. All the existing tests still pass. Added some new tests to cover the case of extra = signs which was not covered before. Signed-off-by: Kir Kolyshkin --- ulimit.go | 22 ++++++++++------------ ulimit_test.go | 6 ++++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/ulimit.go b/ulimit.go index fca0400..9635ceb 100644 --- a/ulimit.go +++ b/ulimit.go @@ -64,13 +64,13 @@ var ulimitNameMapping = map[string]int{ // ParseUlimit parses and returns a Ulimit from the specified string. func ParseUlimit(val string) (*Ulimit, error) { - parts := strings.SplitN(val, "=", 2) - if len(parts) != 2 { + name, val, ok := strings.Cut(val, "=") + if !ok { return nil, fmt.Errorf("invalid ulimit argument: %s", val) } - if _, exists := ulimitNameMapping[parts[0]]; !exists { - return nil, fmt.Errorf("invalid ulimit type: %s", parts[0]) + if _, exists := ulimitNameMapping[name]; !exists { + return nil, fmt.Errorf("invalid ulimit type: %s", name) } var ( @@ -79,21 +79,19 @@ func ParseUlimit(val string) (*Ulimit, error) { temp int64 err error ) - switch limitVals := strings.Split(parts[1], ":"); len(limitVals) { - case 2: - temp, err = strconv.ParseInt(limitVals[1], 10, 64) + switch softStr, hardStr, ok := strings.Cut(val, ":"); ok { + case true: + temp, err = strconv.ParseInt(hardStr, 10, 64) if err != nil { return nil, err } hard = &temp fallthrough - case 1: - soft, err = strconv.ParseInt(limitVals[0], 10, 64) + case false: + soft, err = strconv.ParseInt(softStr, 10, 64) if err != nil { return nil, err } - default: - return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1]) } if *hard != -1 { @@ -105,7 +103,7 @@ func ParseUlimit(val string) (*Ulimit, error) { } } - return &Ulimit{Name: parts[0], Soft: soft, Hard: *hard}, nil + return &Ulimit{Name: name, Soft: soft, Hard: *hard}, nil } // GetRlimit returns the RLimit corresponding to Ulimit. diff --git a/ulimit_test.go b/ulimit_test.go index 401071f..1b1af27 100644 --- a/ulimit_test.go +++ b/ulimit_test.go @@ -51,6 +51,12 @@ func TestParseUlimitBadFormat(t *testing.T) { if _, err := ParseUlimit("nofile=:1024"); err == nil { t.Fatal("expected error on bad syntax") } + if _, err := ParseUlimit("nofile=1024=512"); err == nil { + t.Fatal("expected error on bad syntax") + } + if _, err := ParseUlimit("nofile=1024:512=extra"); err == nil { + t.Fatal("expected error on bad syntax") + } } func TestParseUlimitHardLessThanSoft(t *testing.T) { From 6a3e4f2a525d9e578f3c604ec65591de5c8355bc Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 10 Apr 2026 12:03:47 -0700 Subject: [PATCH 3/3] size.go: use strings.Cut Addressing the TODO item added by commit 7375726. Signed-off-by: Kir Kolyshkin --- size.go | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/size.go b/size.go index c245a89..9d43877 100644 --- a/size.go +++ b/size.go @@ -89,21 +89,16 @@ func RAMInBytes(size string) (int64, error) { // Parses the human-readable size string into the amount it represents. func parseSize(sizeStr string, uMap unitMap) (int64, error) { - // TODO: rewrite to use strings.Cut if there's a space - // once Go < 1.18 is deprecated. - sep := strings.LastIndexAny(sizeStr, "01234567890. ") - if sep == -1 { - // There should be at least a digit. - return -1, fmt.Errorf("invalid size: '%s'", sizeStr) - } - var num, sfx string - if sizeStr[sep] != ' ' { + num, sfx, ok := strings.Cut(sizeStr, " ") + if !ok { + // No space between number and suffix. Find the suffix. + sep := strings.LastIndexAny(sizeStr, "01234567890.") + if sep == -1 { + // There should be at least a digit. + return -1, fmt.Errorf("invalid size: '%s'", sizeStr) + } num = sizeStr[:sep+1] sfx = sizeStr[sep+1:] - } else { - // Omit the space separator. - num = sizeStr[:sep] - sfx = sizeStr[sep+1:] } size, err := strconv.ParseFloat(num, 64)