← Back to Rust Course | Chapter 6: Borrowing & References | Lesson 6 of 6

String Slices

A string slice is a peek at part of some text, borrowed instead of copied, so it's quick and doesn't waste memory.
Syntax
rust
let s = String::from("text");
let part: &str = &s[start..end];
let part = &s[..end];

Creating a String Slice

A string slice references part of a String's data using a byte-range index. It does not own or copy the text -- it simply points into the original string's memory.

Example: Creating a String Slice

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `greeting`, set to `String::from("Hello, world!")`
    let greeting = String::from("Hello, world!");
    // Declare an immutable variable `hello`, set to `&greeting[0..5]`
    let hello = &greeting[0..5];
    // Print "{}" to the console, substituting in `hello` (with a trailing newline)
    println!("{}", hello);
}

String Literals Are Slices

A string literal written directly in source code, like "Rust", has the type &str and lives for the entire duration of the program, since it is embedded directly in the compiled binary.

Example: String Literals Are Slices

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `literal` (a string slice), set to `"I am already a slice"`
    let literal: &str = "I am already a slice";
    // Print "{}" to the console, substituting in `literal` (with a trailing newline)
    println!("{}", literal);
}

Accepting &str in Functions

Writing a function parameter as &str instead of String lets it accept both borrowed String data and string literals, making the function more flexible for callers.

Example: Accepting &str in Functions

markup
// Define the function `first_word` taking `text` and returning a string slice
fn first_word(text: &str) -> &str {
    // Match on `text.find(' ')` and branch by pattern
    match text.find(' ') {
        Some(index) => &text[..index],
        None => text,
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `sentence`, set to `String::from("Rust is fun")`
    let sentence = String::from("Rust is fun");
    // Print "{}" to the console, substituting in `first_word(&sentence)` (with a trailing newline)
    println!("{}", first_word(&sentence));
}

Slicing on Character Boundaries

Because Rust strings are UTF-8 encoded, slice indices must land on valid character boundaries.

Slicing through the middle of a multi-byte character causes a runtime panic, so text-safe code often uses methods like .chars() instead of raw byte indices.

Example: Slicing on Character Boundaries

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `word`, set to `"Rust"`
    let word = "Rust";
    // Declare an immutable variable `piece`, set to `&word[0..2]`
    let piece = &word[0..2];
    // Print "First two bytes: {}" to the console, substituting in `piece` (with a trailing newline)
    println!("First two bytes: {}", piece);
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Trying to slice a String in the middle of a multi-byte UTF-8 character, which panics at runtime.
  2. Using String everywhere a function only needs to read text, when accepting &str would work for both owned strings and literals.
  3. Assuming &str and String are the same type -- &str is a borrowed view while String is an owned, growable buffer.
Chapter Summary
  • &str is an immutable reference to some UTF-8 text, either borrowed from a String or a string literal.
  • String slices use byte-index ranges, e.g. &text[0..5], and must fall on valid UTF-8 character boundaries.
  • String literals like "hello" are already &str slices with a 'static lifetime.
  • Functions that only need to read string data should typically accept &str rather than String for maximum flexibility.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.