Im Primitive-Datentypen-Kapitel hast du Slices schon kurz kennengelernt. Dieses Kapitel vertieft sie als das, was sie wirklich sind: die universelle View-Form in Rust. Praktisch jede Funktion, die mit einer Sequenz zu tun hat — egal ob String, Vec, Array oder eingehender Network-Buffer — nimmt einen Slice als Parameter. Wer Slices beherrscht, schreibt Funktions-Signaturen, die mit jedem Aufrufer zurechtkommen, ohne unnötige Allokationen oder unnötige Generics. Wir gehen tief in &str, &[T], mutable Slices, das mächtige Slice-Pattern-Matching, und schließen mit windows/chunks als Iteratoren für gleitende und feste Fenster.
Warum Slices?
Eine Funktion, die mit einer Sequenz arbeitet, hat in anderen Sprachen drei schlechte Optionen:
- Verbraucht den Container —
fn foo(v: Vec<T>)zwingt den Aufrufer zum Move. - Borrowt den konkreten Container —
fn foo(v: &Vec<T>)schließt Arrays und Sub-Bereiche aus. - Wird generisch —
fn foo<I: IntoIterator<Item = T>>(it: I)ist mächtig, aber syntaktisch teuer.
Rust hat die vierte Option: Slices. Eine Slice-Referenz (&[T], &str, &mut [T]) ist ein Fat Pointer — Pointer + Länge — und passt zu Arrays, Vecs, Sub-Bereichen und sogar zu C-FFI-Buffern.
fn summe(v: &[i32]) -> i32 {
v.iter().sum()
}
fn main() {
let array = [1, 2, 3];
let vec = vec![10, 20, 30];
assert_eq!(summe(&array), 6); // Array
assert_eq!(summe(&vec), 60); // Vec
assert_eq!(summe(&vec[1..]), 50); // Sub-Slice
}Drei Container-Typen, eine Funktion, eine Signatur. Slices sind die idiomatische Lösung.
Die Slice-Familie
| Typ | Bedeutung | Wann nutzen |
|---|---|---|
&str | String-Slice (UTF-8-validiert) | String-Parameter, Text-Verarbeitung |
&mut str | Mutable String-Slice | Selten — In-Place-Text-Manipulation |
&[T] | Element-Slice (read-only) | Sequenzen lesen |
&mut [T] | Element-Slice (mutable) | Sequenzen in-place bearbeiten |
Box<[T]> | Owned Slice | Wenn Vec-Wachstum nicht mehr nötig |
Alle teilen sich dieselbe interne Struktur: Pointer + Länge (16 Bytes auf 64-bit-Systemen). Der Compiler weiß zur Compile-Zeit nichts über die konkrete Länge — sie wird zur Laufzeit aus dem Fat Pointer gelesen.
Was dich erwartet
- String-Slice
&str— der spezielle String-Slice mit UTF-8-Garantie,&'static str-Literale, die Unterschiede zuString-owned, und alle wichtigenstr-Methoden. - Array-Slices
&[T]— der allgemeine Element-Slice. Range-Syntax (..,..n,n..,n..m,..=m), Auto-Deref-Coercion und die wichtigsten Methoden. - Mutable Slices —
&mut [T]und seine Eigenheiten:split_at_mutfür disjunkte Mutation,iter_mut,swap,fill, und die typischen Borrow-Checker-Konflikte. - Slice-Patterns — Pattern-Matching auf Slice-Länge und -Inhalten:
[first, ..],[.., last],[a, b, c],[head, middle @ .., tail], und der Einsatz inmatch/let. - windows und chunks — Iteratoren über überlappende (
windows) und disjunkte (chunks) Fenster. Pluschunks_exactfür Vektorisierung-freundliche Pipelines.
Was du nach diesem Kapitel kannst
- Funktions-Signaturen mit Slice-Parametern entwerfen, die mit Array, Vec und Sub-Slice umgehen können.
&strvs.Stringsicher unterscheiden und in API-Designs die richtige Wahl treffen.- Mutable Slices nutzen, ohne Borrow-Checker-Konflikte zu produzieren — inklusive
split_at_mutfür disjunkte Borrows. - Slice-Patterns für elegante Length-Checks und Element-Extraktion einsetzen.
windowsundchunksfür klassische Streaming- und Pattern-Such-Algorithmen verwenden.
Im nächsten Kapitel geht es um Structs und Methoden — wie eigene Datentypen mit Verhalten kombiniert werden.