为何if中可比较String与&str,使用match时却报错?
为什么Rust中用match匹配String和字符串字面量会报错?
这问题我刚学Rust的时候也踩过一模一样的坑!让我给你掰扯清楚原因和解决办法:
核心原因:类型不匹配
你定义的s是String类型(堆分配的可增长字符串),而"holla!"是&str类型(字符串切片,指向字符串数据的引用)。
- 在
if语句里能正常比较,是因为Rust为String和&str实现了PartialEqtrait,允许跨类型做相等性检查,底层会自动把String转成&str来比较。 - 但
match的模式匹配是严格的类型检查,它要求匹配的模式和被匹配的值必须是完全相同的类型,不会自动做类型转换,所以直接用match s去匹配"holla!"(&str)就会报错。
解决办法
这里有几种常用的方案,你可以根据场景选:
1. 将String转为&str再匹配(最常用)
用as_str()方法或者切片语法&s[..]把String转换成&str,这样模式和被匹配值类型就一致了:
fn main() { let s = String::from("holla!"); match s.as_str() { "holla!" => println!("it worked!"), _ => println!("nothing"), } }
2. 使用匹配守卫(match guard)
如果不想转换类型,可以在模式里用ref获取引用,再通过守卫条件做相等性检查:
fn main() { let s = String::from("holla!"); match s { ref s_val if s_val == "holla!" => println!("it worked!"), _ => println!("nothing"), } }
这里的ref是为了避免获取s的所有权(如果不用ref,s会被移动到模式里,后面就没法用了)。
3. 直接使用&str类型(如果场景允许)
如果你的字符串不需要修改或者从堆分配,一开始就用&str类型:
fn main() { let s: &str = "holla!"; match s { "holla!" => println!("it worked!"), _ => println!("nothing"), } }
不过如果是读取命令行参数的话,命令行参数返回的是String,所以这种方法只适用于静态字符串的场景。
总结
match的模式匹配规则比if的相等检查严格得多,必须保证类型完全一致。对于String和&str的匹配,最通用的做法就是把String转换成&str再进行匹配~
内容的提问来源于stack exchange,提问作者robfuscator
相关产品推荐
相关产品推荐

