string slice

rust的slice和golang的类似,一个 fat pointer 指向原始地址,它和 &String类似,但不一样的是,它能保证slice的生命周期和原始地址的内容一致

image.png

举个例子

比如我们要截取一个字符串中的第一个单词,通常会这么写

  1. fn first_word(s: &String) -> usize {
  2. let bytes = s.as_bytes();
  3. for (i, &item) in bytes.iter().enumerate() {
  4. if item == b' ' {
  5. return i;
  6. }
  7. }
  8. s.len()
  9. }
  1. fn main() {
  2. let mut s = String::from("hello world");
  3. let f = first_word(&s);
  4. println!("first word is at index of {}", f);
  5. }

但这时候假如在后面修改了s的值

  1. fn main() {
  2. let mut s = String::from("hello,world");
  3. let f = first_word(&s);
  4. s.clear();
  5. println!("first comma is at index of {}", f);
  6. }

这时候对f来说就没有意义了,因为这时候的index所对应的字符串已经变了,但这时候编译这段代码是没有问题的。如果我们希望 first_comma 这个函数的生命周期和入参保持一致,就可以用slice

  1. fn first_word(s: &String) -> &str {
  2. let bytes = s.as_bytes();
  3. for (i, &item) in bytes.iter().enumerate() {
  4. if item == b' ' {
  5. return &s[0..i];
  6. }
  7. }
  8. &s[..]
  9. }

这时候编译就会报错,原因是在一个scope中,mutable borrow和 immutable borrow是互斥的,可以有多个immutable borrow,有点像 rwlock的意思
image.png

大多数情况下 &String 入参也能替换成 &str, &str实现了&String中大多数的方法