切片 (slice)
用于引用一个集合(比如数组、字符串)的一段连续部分(子集)而不需要拥有这些元素的所有权。
比较常见的用法有 字符串切片类型 &str
。
字符串字面量是 slice
类型,数据被硬编码在可执行二进制文件中,程序使用字符串切片来访问它。
字符串类型的变量有一个字符串数据在内存中起始位置的指针,表示有关字符串长度和容量的信息。
let sentence = String::from("This is a sequence of words.");
println!("sentence is {}", sentence); // sentence is This is a sequence of words.
let last_word = &sentence[22..22 + 5];
println!("last_word is \"{}\"", last_word); // last_word is "words"
last_word
变量有一个指向字符串数据部分的 偏移/起始 索引的指针以及切片长度。
通常切片的结束索引不包含在结果中。(不包含第 5 位)
从起始位置到末尾的切片:
let last_part: &str = &sentence[22..];
println!("last_part is \"{}\"", last_part); // last_part is "words."
字符串切片的长度以字节数为单位,使用 usize
类型。不是字符串中字符的数量
let slice_length: usize = last_part.len();
println!("slice_length is {} bytes", slice_length); // slice_length is 6 bytes
当使用字符串切片索引取值的时候应特别注意,UTF-8
编码会占用 1 到 4 字节,而不是固定的字节。索引值必须在字符的边界处,否则程序会 panic
。所以在创建字符串的时候谨慎使用特殊字符或是表情。
在 Node.js
中我们是不太会关注这些底层问题。
Slices 类型作为参数
我们创建一个函数用来获取一句话的第一个词语:
fn get_first_word(msg: &String) -> &str {
// 从字符串语句中创建一个字节类型的 slice (&[u8])
let bytes: &[u8] = msg.as_bytes();
// 遍历这个 bytes ,并使用 enumerate() 获取每次的索引值
for (index, &item) in bytes.iter().enumerate() {
// 找到第一个空格,并将之前的所有内容作为 string slice 返回
// 一个空格的字节表示为 b' '
// 我们正在迭代的是 字节 而不是 字符串
// 这样做是因为 索引值 是因为字符串切片的索引是以 字节 为单位的
if item == b' ' {
return &msg[..index];
}
}
// 如果没有找到空格则返回全部
&msg
}
let message = String::from("lorem ipsum");
let first_word = get_first_word(&message);
println!("first_word is \"{}\"", first_word); // first_word is "lorem"
let first_word_too = get_first_word_too(&message[6..]);
println!("first_word_too is \"{}\"", first_word_too); // first_word_too is "ipsum"