String Slices
In this page:
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
// 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);
}
Login to try C/C++/Java/PHP code in the editor
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
// 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);
}
Login to try C/C++/Java/PHP code in the editor
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
// 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));
}
Login to try C/C++/Java/PHP code in the editor
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
// 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);
}
Login to try C/C++/Java/PHP code in the editor
- Trying to slice a
Stringin the middle of a multi-byte UTF-8 character, which panics at runtime. - Using
Stringeverywhere a function only needs to read text, when accepting&strwould work for both owned strings and literals. - Assuming
&strandStringare the same type --&stris a borrowed view whileStringis an owned, growable buffer.
&stris an immutable reference to some UTF-8 text, either borrowed from aStringor 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&strslices with a'staticlifetime. - Functions that only need to read string data should typically accept
&strrather thanStringfor maximum flexibility.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: