Repeated slice patterns show up in test fixtures, cyclic configuration data, padding schemes, and small generated sequences. slices.Repeat handles that shape directly: it returns a new slice containing the input sequence repeated a specified number of times.
The result has a defined size and separate slice storage. Its boundary cases also matter, especially when the repeat count comes from external input or arithmetic.
Build a repeated pattern with slices.Repeat
A count of three copies the complete input sequence three times:
package main
import (
"fmt"
"slices"
)
func main() {
pattern := []string{"read", "write"}
repeated := slices.Repeat(pattern, 3)
fmt.Println(repeated)
}The output is:
[read write read write read write]The operation repeats the slice as a unit. It doesn’t repeat each element individually. For []int{1, 2} with a count of three, the result is []int{1, 2, 1, 2, 1, 2} rather than []int{1, 1, 1, 2, 2, 2}.
That distinction is useful when the input represents an ordered cycle rather than a bag of values.
Result length and capacity are predictable
For an input of length n and a non-negative count c, the returned slice has both length and capacity equal to n * c.
pattern := []int{10, 20, 30}
repeated := slices.Repeat(pattern, 4)
fmt.Println(len(repeated)) // 12
fmt.Println(cap(repeated)) // 12There is no spare capacity promised beyond the repeated data. Appending another element may therefore require new backing storage.
The exact size also makes validation straightforward when a count could be unexpectedly large. Repetition allocates space proportional to the product of the input length and count, so accepting an unchecked count can request far more memory than the application intended.
The returned slice has separate storage
slices.Repeat creates a new result rather than extending the input in place. Changing a top-level element in the result doesn’t rewrite the corresponding element in the source:
pattern := []int{1, 2}
repeated := slices.Repeat(pattern, 2)
repeated[0] = 99
fmt.Println(pattern) // [1 2]
fmt.Println(repeated) // [99 2 1 2]For element types that themselves contain references, the distinction is shallower. Repeating a slice of pointers copies pointer values. Repeating structs that contain slices, maps, or pointers copies those fields as values, so nested referenced data can still be shared.
If every repeated element needs independent nested state, slices.Repeat alone doesn’t provide a deep copy. That state needs to be copied according to the element type’s ownership rules.
Zero count returns an empty non-nil slice
A count of zero produces a slice with zero length and zero capacity. The result is not nil.
values := slices.Repeat([]int{1, 2, 3}, 0)
fmt.Println(len(values)) // 0
fmt.Println(values == nil) // falseThe result is also non-nil when the input itself is nil:
var source []int
values := slices.Repeat(source, 3)
fmt.Println(len(values)) // 0
fmt.Println(values == nil) // falseThis differs from some slice helpers that preserve nilness. Code that treats nil and empty slices as distinct states should account for that behavior rather than assuming repetition preserves the source representation.
Negative counts and size overflow panic
A negative repeat count is invalid and causes a panic. The function also panics if len(x) * count overflows the integer range.
That makes count validation appropriate at boundaries where the value isn’t already constrained:
func repeatPattern(pattern []byte, count int) ([]byte, error) {
if count < 0 || count > 1024 {
return nil, fmt.Errorf("repeat count out of range")
}
return slices.Repeat(pattern, count), nil
}The upper bound in real code should come from the application’s data limits, not from slices.Repeat itself. A count can be valid for integer arithmetic and still produce an allocation that is unreasonable for the process.
Repetition is different from preallocation
slices.Repeat is appropriate when the desired output is the same complete sequence copied several times. It isn’t a replacement for make when code merely needs capacity for values that will be generated independently.
For example, make([]T, 0, n) reserves capacity while keeping the length at zero. slices.Repeat(pattern, n) immediately creates len(pattern) * n initialized elements. Those operations express different data states and shouldn’t be interchanged just because both can allocate a slice.
Keep the count tied to a real bound
slices.Repeat makes repeated patterns concise without hiding their size: the result is a new, non-nil slice with length and capacity equal to the input length multiplied by the count.
The main boundary is the count itself. When it comes from a trusted small constant, the operation is simple. When it comes from a request, file, or calculation, constrain it before repetition so the allocation remains within the application’s intended limits.