diff --git a/src/strings/strings.go b/src/strings/strings.go index 9e7d4f0455982b..59f70da845512d 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -535,23 +535,33 @@ func Map(mapping func(rune) rune, s string) string { // It panics if count is negative or if // the result of (len(s) * count) overflows. func Repeat(s string, count int) string { + if count == 0 { + return "" + } + // Since we cannot return an error on overflow, // we should panic if the repeat will generate // an overflow. // See Issue golang.org/issue/16237 if count < 0 { panic("strings: negative Repeat count") - } else if count > 0 && len(s)*count/count != len(s) { + } else if len(s)*count/count != len(s) { panic("strings: Repeat count causes overflow") } - b := make([]byte, len(s)*count) - bp := copy(b, s) - for bp < len(b) { - copy(b[bp:], b[:bp]) - bp *= 2 + n := len(s) * count + var b Builder + b.Grow(n) + b.WriteString(s) + for b.Len() < n { + if b.Len() <= n/2 { + b.WriteString(b.String()) + } else { + b.WriteString(b.String()[:n-b.Len()]) + break + } } - return string(b) + return b.String() } // ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case. diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index 78bc573e5f0bf1..b5c648574939f7 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -1647,8 +1647,15 @@ func BenchmarkSplitNMultiByteSeparator(b *testing.B) { } func BenchmarkRepeat(b *testing.B) { - for i := 0; i < b.N; i++ { - Repeat("-", 80) + s := "0123456789" + for _, n := range []int{5, 10} { + for _, c := range []int{1, 2, 6} { + b.Run(fmt.Sprintf("%dx%d", n, c), func(b *testing.B) { + for i := 0; i < b.N; i++ { + Repeat(s[:n], c) + } + }) + } } }