Files
gookit-goutil/PR.md
T
dualfroz e2e5b5495f fix(strutil): keep center-aligned Resize within the requested length
The center branch of resize() added the odd-padding space whenever the
input was non-empty, because the parity check omitted the source length
(wantLen - padLn*2 instead of wantLen - sLen - padLn*2). This made Resize,
Align and their utf8 variants overflow wantLen by one for every non-empty
string with an even amount of padding. Subtract sLen so the extra space is
only added when the total padding is actually odd.
2026-09-04 09:07:10 +02:00

2.3 KiB

fix(strutil): center-aligned Resize/Align overflows the requested length

Problem

strutil.Resize / strutil.Align (and their utf8 variants) with comdef.Center alignment produce strings longer than the requested length for almost every non-empty input:

strutil.Resize("ab", 6, comdef.Center)   // "  ab   " (len 7), want "  ab  " (len 6)
strutil.Resize("ab", 4, comdef.Center)   // " ab  "   (len 5), want " ab "   (len 4)
strutil.Resize("abc", 7, comdef.Center)  // "  abc   "(len 8), want "  abc  "(len 7)

The extra space that centers an odd amount of padding is added unconditionally whenever the input is non-empty, not only when the padding is actually odd.

Root cause

strutil/padding.go, resize:

if align == comdef.Center {
    padLn := (wantLen - sLen) / 2
    if diff = wantLen - padLn*2; diff > 0 {  // wrong: missing "- sLen"
        s += " "
    }
    ...
}

The condition is meant to detect an odd amount of total padding (wantLen - sLen). Simplifying the buggy expression:

wantLen - 2*padLn = wantLen - 2*floor((wantLen-sLen)/2)
                  = sLen + ((wantLen - sLen) mod 2)

so diff > 0 is true whenever sLen > 0, regardless of the padding parity. The result is one space too long for every non-empty string with even padding.

The existing TestResize("title", 20, PosMiddle) case did not catch this because its padding (15) is odd, where the extra space is legitimately needed.

Fix

Compare against the actual leftover padding by subtracting sLen:

if diff = wantLen - sLen - padLn*2; diff > 0 {
    s += " "
}

This adds the extra space only when (wantLen - sLen) is odd, keeping the odd case (e.g. the "title" test) unchanged.

Test

Added TestResize_center_length in strutil/padding_test.go asserting both the exact result and len(result) == wantLen for even- and odd-padding cases.

  • Gate: go test ./strutil/ -run TestResize -> ok (PASS)
  • go vet ./strutil/ -> exit 0
  • go build ./... -> exit 0

Counterfactual: reverting the change makes the new test fail with actual: int(7) / actual: " ab " vs the expected length 6 / " ab ".

Note: TestDateSNv3/dateLen4_base62 in strutil/gensn_test.go is flaky and already fails on the unmodified base commit (it asserts uniqueness of randomly generated serial numbers); it is unrelated to this change.