string slice
rust的slice和golang的类似,一个 fat pointer
指向原始地址,它和 &String类似,但不一样的是,它能保证slice的生命周期和原始地址的内容一致
举个例子
比如我们要截取一个字符串中的第一个单词,通常会这么写
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
fn main() {
let mut s = String::from("hello world");
let f = first_word(&s);
println!("first word is at index of {}", f);
}
但这时候假如在后面修改了s的值
fn main() {
let mut s = String::from("hello,world");
let f = first_word(&s);
s.clear();
println!("first comma is at index of {}", f);
}
这时候对f来说就没有意义了,因为这时候的index所对应的字符串已经变了,但这时候编译这段代码是没有问题的。如果我们希望 first_comma
这个函数的生命周期和入参保持一致,就可以用slice
fn first_word(s: &String) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
这时候编译就会报错,原因是在一个scope中,mutable borrow和 immutable borrow是互斥的,可以有多个immutable borrow,有点像 rwlock的意思
大多数情况下 &String
入参也能替换成 &str, &str实现了&String中大多数的方法