slices.Repeat builds a new slice by concatenating a source slice with itself a specified number of times. The operation is small, but its exact contract matters when code depends on allocation, nil state, or reference-bearing elements.
The function belongs to the standard slices package and has this signature:
func Repeat[S ~[]E, E any](x S, count int) SThe returned slice has both length and capacity equal to len(x) * count. The result is never nil.
Repetition preserves sequence boundaries
Repeat copies the complete source sequence for each repetition. It does not repeat each element independently.
package main
import (
"fmt"
"slices"
)
func main() {
pattern := []int{1, 4, 9}
values := slices.Repeat(pattern, 3)
fmt.Println(values)
}The output is:
[1 4 9 1 4 9 1 4 9]That distinction is useful for data built from fixed motifs: protocol test vectors, cyclic lookup tables, repeated delimiters, or synthetic input where a whole sequence is the unit being duplicated.
The result owns separate outer slice storage
The returned slice is new. Mutating a scalar element in the repeated result does not rewrite the corresponding scalar in the source slice.
source := []int{2, 5}
repeated := slices.Repeat(source, 2)
repeated[0] = 99
fmt.Println(source) // [2 5]
fmt.Println(repeated) // [99 5 2 5]This separates the outer slice storage. It does not turn reference-bearing elements into independent objects.
If the element type is a pointer, map, slice, channel, or another value that refers to shared state, Repeat copies that element value into each position. Those copied values can still refer to the same underlying object.
type Config struct {
Enabled bool
}
cfg := &Config{Enabled: false}
items := slices.Repeat([]*Config{cfg}, 3)
items[1].Enabled = true
fmt.Println(items[0].Enabled) // true
fmt.Println(items[2].Enabled) // trueAll three elements contain the same pointer. The new outer slice therefore prevents outer-array aliasing with the source while leaving element-level reference relationships intact.
Zero repetitions produce a non-nil empty slice
A count of zero yields an empty result with zero length and zero capacity. The result is still non-nil.
values := slices.Repeat([]string{"a", "b"}, 0)
fmt.Println(len(values)) // 0
fmt.Println(cap(values)) // 0
fmt.Println(values == nil) // falseThe same contract applies when the source itself is nil:
var source []int
values := slices.Repeat(source, 4)
fmt.Println(len(values)) // 0
fmt.Println(values == nil) // falseCode that uses nil and empty slices as distinct states should account for that normalization.
Invalid counts fail before a usable result exists
Negative repetition counts are rejected with a panic. A panic also occurs when len(x) * count overflows the size calculation for the result.
values := []int{1, 2, 3}
_ = slices.Repeat(values, -1) // panicA caller that accepts an external or computed repetition count should validate that value before invoking Repeat when panic-based failure is not appropriate for the surrounding API.
The size rule also makes memory growth explicit. Repeating a large source many times requires storage for the full materialized result. Repeat is not a lazy sequence and does not defer copies until iteration.
Named slice types remain named slice types
The type parameter S ~[]E allows Repeat to accept user-defined slice types whose underlying type is a slice. The return type is the same S.
type Bytes []byte
prefix := Bytes{0xAA, 0x55}
frame := slices.Repeat(prefix, 2)
fmt.Printf("%T %v\n", frame, frame)
// main.Bytes [170 85 170 85]That preservation avoids an extra conversion when an API uses a named slice type to carry domain meaning or attach methods.
Materialization is the defining boundary
slices.Repeat is a direct fit when the desired value is a concrete repeated slice with known final size. Its contract is explicit: allocate a new outer slice, copy the source sequence count times, return exact length and capacity, and produce a non-nil result even when empty.
That boundary also marks cases that need another shape. Large or unbounded repetition is better represented as iteration or generation rather than a fully materialized slice, while reference-bearing elements may require explicit cloning when independent nested state is required.