Rust格式化转义字符疑问:通过的测试是否违背相等性预期?
我在处理Rust的格式化转义字符时遇到问题,注意到格式化字符串'{}'中的单引号场景。我运行了如下测试用例,结果显示测试全部通过,请问该通过的测试是否与对字符串相等性的预期相悖?
测试代码
#[test] fn test_parse_escape_char() { assert_eq!(format!("'{}'", "O'Grady"), "'O'Grady'"); assert_eq!(format!("'{}'", "O'Grady"), "'O\'Grady'"); assert_eq!("O'Grady", "O'Grady"); assert_eq!("O'Grady", "O\'Grady"); }
测试结果
test tests::test_parse_escape_char ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 41 filtered out; finished in 0.00s
测试通过的原因(完全符合预期)
这一点都不矛盾,核心在于Rust里字符串字面量的转义符\是编译阶段的语法标记,不会成为字符串实际内容的一部分:
直接字符串比较的两个断言:
"O'Grady"和"O\'Grady"在编译后,最终存在内存里的字符序列完全一样——都是O、'、G、r、a、d、y。转义符只是告诉编译器:后面的单引号是普通字符,不是用来结束这个字符串的,所以两者自然相等。format!相关的断言:format!("'{}'", "O'Grady")生成的结果是'O'Grady'(开头和结尾的单引号来自模板,中间的单引号来自输入字符串)。而断言右边的"'O\'Grady'",编译后实际存储的内容也是'O'Grady'——转义符只是为了在代码里写这个字符串时,避免中间的单引号被当成字符串结束标记,所以和format!的输出完全一致,断言自然通过。
总结:代码里的\是给编译器看的语法辅助符号,不是字符串本身的内容,只要最终内存里的字符序列相同,assert_eq!就会判定相等。
内容的提问来源于stack exchange,提问作者A Boston

