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) S

The 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) // true

All 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)  // false

The 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) // false

Code 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) // panic

A 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.