切片
你会学到什么
- 切片
&[T]是对连续序列的借用视图,不拥有数据。 &[i32]同时接受数组、Vec和切片,是函数参数的首选。- 字符串切片
&str指向String的一段字节。
最小示例
let numbers = [1, 2, 3, 4, 5];
let middle = &numbers[1..4]; // [2, 3, 4]
println!("{middle:?}");
运行代码
cd examples
cargo run -p rt_08_slices
cargo test -p rt_08_slices
代码讲解
用 &[T] 而不是 &Vec<T> 做参数,能让函数更通用:
fn sum(values: &[i32]) -> i32 {
values.iter().sum()
}
sum(&array)、sum(&vec)、sum(&vec[1..3]) 都能调用。
切片用 range 语法创建,&s[a..b] 包含 a 不含 b:
fn first_word(text: &str) -> &str {
match text.find(' ') {
Some(index) => &text[..index],
None => text,
}
}
常见错误
字符串切片必须落在字符边界上,否则运行时 panic:
let s = String::from("中文");
let bad = &s[0..1]; // ❌ byte index 1 is not a char boundary
处理多字节文本时用 chars() 或 char_indices() 而不是直接按字节切。
练习
- 写一个函数返回切片的最后一个元素
Option<&i32>。 - 写一个函数把
&str按第一个空格拆成(&str, &str)。
小结
切片是零拷贝的借用视图。优先用 &[T] 和 &str 做参数类型,让接口更灵活。
下一步
当引用要存进结构体或跨函数返回时,需要生命周期标注。下一章学习生命周期。
完整示例代码
下面是 examples/08_slices/ 的完整源码。无需 clone 仓库,直接在页面上阅读、复制、对照运行。
examples/08_slices/src/main.rs
//! 切片:对连续序列的借用视图。
/// `&[i32]` 同时接受数组、`Vec` 和切片。
fn sum(values: &[i32]) -> i32 {
values.iter().sum()
}
/// 返回去掉首尾元素后的子切片。
fn middle(values: &[i32]) -> &[i32] {
if values.len() < 2 {
&[]
} else {
&values[1..values.len() - 1]
}
}
/// 字符串切片 `&str` 指向原字符串的一段。
fn first_word(text: &str) -> &str {
match text.find(' ') {
Some(index) => &text[..index],
None => text,
}
}
fn main() {
let numbers = [1, 2, 3, 4, 5];
println!("sum = {}", sum(&numbers));
println!("middle = {:?}", middle(&numbers));
println!("first word = {}", first_word("hello rust world"));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sums_any_slice() {
assert_eq!(sum(&[1, 2, 3]), 6);
let owned = vec![10, 20];
assert_eq!(sum(&owned), 30);
}
#[test]
fn takes_middle() {
assert_eq!(middle(&[1, 2, 3, 4]), &[2, 3]);
assert_eq!(middle(&[1]), &[] as &[i32]);
}
#[test]
fn slices_first_word() {
assert_eq!(first_word("hello world"), "hello");
assert_eq!(first_word("single"), "single");
}
} examples/08_slices/Cargo.toml
[package]
name = "rt_08_slices"
version.workspace = true
edition.workspace = true
publish.workspace = true