Rust 学习笔记 07:Slice 类型
“Slice and dice your data safely.”
在 Go 语言中,Slice (切片) 是一个非常核心的概念,它底层是一个结构体 (ptr, len, cap)。
在 Rust 中,Slice 也是类似的,但它有一个本质的区别:Rust 的 Slice 是一种引用(Borrowed Type)。
它不拥有数据,它只是借用了数据的一部分。
1. 字符串切片 (String Slices)
假设我们有一个字符串 s:
1let s = String::from("hello world");
我们可以创建一个切片,指向它的一部分:
1let hello = &s[0..5]; // 指向 0,1,2,3,4
2let world = &s[6..11];
注意那个 & 符号,说明 hello 是一个引用。
它的类型是 &str(读作 “string slice”)。它内部包含两个字段:
- 指向数据的指针 (ptr)
- 切片的长度 (len)
这和 Go 的 Slice 结构几乎一样,只是少了容量 (cap),且必须依附于原字符串存在。
2. 切片与所有权
既然 Slice 是引用,它就受借用规则的约束。
1let mut s = String::from("hello world");
2let word = first_word(&s); // word 借用了 s
3
4s.clear(); // 错误!试图获取可变引用来修改 s
5// 但 s 已经被 immutable borrow (借给 word) 了。
6
7println!("the first word is: {}", word);
编译器会阻止我们在切片依然有效时,去修改原数据。这避免了悬垂引用(dangling pointer),即切片指向了无效内存。
3. 都可以是 Slice
有没有发现,函数的参数如果定义为 &str,它既能接收 String 的切片,也能接收字符串字面量?
1fn first_word(s: &str) -> &str { ... }
2
3let s = String::from("Hello");
4first_word(&s); // 传 String 的引用(自动强转为 slice)
5first_word(&s[..]); // 传全切片
6
7first_word("Hello"); // 传字面量(字面量本身就是 &str)
所以,在定义函数参数时,能用 &str 就尽量用 &str,而不是 &String。这会让函数更通用。
4. 数组切片
除了字符串,普通数组也可以切片。
1let a = [1, 2, 3, 4, 5];
2let slice = &a[1..3]; // 类型是 &[i32]
用法和字符串切片完全一样。
5. 小结
第七篇笔记,我们补全了 Rust 引用体系的重要一环 —— Slice。
- Slice 是不持有所有权的引用。
&str是字符串切片,比&String更轻量、更通用。- Slice 让你安全地访问集合的一部分,且不用担心内存安全(编译器看着呢)。
至此,Rust 的"所有权三部曲"(所有权、借用、切片)终于讲完了。 这三座大山翻过去之后,接下来的内容(结构体、枚举)对 Go 开发者来说就亲切多了。
下一篇,我们将学习 结构体 (Structs)。你会发现 Rust 的 Struct 和 Go 的很像,但也有一些奇怪的变体(比如元组结构体)。
练习题:
- 编写一个函数,接收一个整数数组切片
&[i32],返回其中最大的元素。 - 尝试使用切片操作中文子串,例如
"你好世界"[0..1],看看会发生什么?(提示:UTF-8 编码)。
思考题:
Go 的 Slice 可以动态扩容(append),Rust 的 Slice (&[T]) 可以扩容吗?为什么?如果想用可变长度的数组,应该用什么类型?
本文代码示例:
关注公众号:极客老墨
更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。
