Rust 中的匹配字符串

Matching string in Rust

我是 Rust (1.31) 的新手,我想了解一段无法编译的简单代码:

fn main() {
    s = String::from("foo");
    match s {
        "foo" => {
            println!("Yes");
        }
        _ => {
            println!("No");
        }
    }
}

相关的错误是:

10 |         "foo" => {                                                                                 
   |         ^^^^^ expected struct `std::string::String`, found reference

出现这个错误后,我决定将代码更改为:

fn main() {
    let s = String::from("foo");

    match s {
        String::from("foo") => {
            println!("Yes");
        }
        _ => {
            println!("No");
        }
    }
}

这样做,我希望得到正确的类型,但事实并非如此:

10 |         String::from("foo") => {                                                                   
   |         ^^^^^^^^^^^^^^^^^^^ not a tuple variant or struct

我对编译器的这条消息感到很困惑,最后我设法通过实现使其工作:

fn main() {
    let s = String::from("foo");

    match &s as &str {
        "foo" => {
            println!("Yes");
        }
        _ => {
            println!("No");
        }
    }
}

但是,我不理解使该解决方案成为正确解决方案的潜在机制以及为什么我的第二个示例不起作用。

第一个示例不起作用,因为 s 是类型 String,它是一个字符串变体,它拥有其中的数据。它与字符串文字(可用作类型 &str)匹配。 match 不明白如何比较这两种不同的类型,所以它会出错。

但是 String 通过实施 Deref<Target=str> 取消对 &str 的引用,这意味着可以在需要 &str 的地方使用对 String 的引用,例如将其与一个进行比较。这就是第三个示例中发生的情况。通过创建引用 &s,可以发生隐式取消引用,并且两种类型可以比较。

您可以使用从 String:

创建 &str 的显式方法,用更少的魔法实现同样的事情
fn main() {
    let s = String::from("foo");

    match s.as_str() {
        "foo" => {
            println!("Yes");
         },
         _ => {
             println!("No");
         }
    }
}

第二个例子试图使事物具有可比性,使 String 成为通用类型而不是 &str。它不起作用,因为 match 需要左侧的模式,而不是创建新结构(并且也在幕后分配)的函数调用。即使它可行(例如通过将 String 创建移动到匹配之外),这种方法也不太理想,因为新的 String 需要内存分配。