Rust 中的“ r #”# 操作符是什么?

我看到操作员 r#""在锈,但我不能找到它做什么。它在创建 JSON 时派上了用场:

let var1 = "test1";
let json = r#"{"type": "type1", "type2": var1}"#;
println!("{}", json) // => {"type2": "type1", "type2": var1}

操作员 r#""的名字是什么? 如何让 var1求值?

45978 次浏览

I can't find what it does

It has to do with string literals and raw strings. I think it is explained pretty well in this part of the documentation, in the code block that is posted there you can see what it does:

"foo"; r"foo";                     // foo
"\"foo\""; r#""foo""#;             // "foo"


"foo #\"# bar";
r##"foo #"# bar"##;                // foo #"# bar


"\x52"; "R"; r"R";                 // R
"\\x52"; r"\x52";                  // \x52

It negates the need to escape special characters inside the string.

The r character at the start of a string literal denotes a raw string literal. It's not an operator, but rather a prefix.

In a normal string literal, there are some characters that you need to escape to make them part of the string, such as " and \. The " character needs to be escaped because it would otherwise terminate the string, and the \ needs to be escaped because it is the escape character.

In raw string literals, you can put an arbitrary number of # symbols between the r and the opening ". To close the raw string literal, you must have a closing ", followed by the same number of # characters as there are at the start. With zero or more # characters, you can put literal \ characters in the string (\ characters do not have any special meaning). With one or more # characters, you can put literal " characters in the string. If you need a " followed by a sequence of # characters in the string, just use the same number of # characters r7 to delimit the string. For example: r3 represents the string r4. The literal doesn't stop at the quote in the middle, because it's only followed by one #, whereas the literal was started with two #.

To answer the last part of your question, there's no way to have a string literal that evaluates variables in the current scope. Some languages, such as PHP, support that, but not Rust. You should consider using the format! macro instead. Note that for JSON, you'll still need to double the braces, even in a raw string literal, because the string is interpreted by the macro.

fn main() {
let var1 = "test1";
let json = format!(r#"\{\{"type": "type1", "type2": {}}}"#, var1);
println!("{}", json) // => {"type2": "type1", "type2": test1}
}

If you need to generate a lot of JSON, there are many crates that will make it easier for you. In particular, with serde_json, you can define regular Rust structs or enums and have them serialized automatically to JSON.

The first time I saw this weird notation is in glium tutorials (old crate for graphics management) and is used to "encapsulate" and pass GLSL code (GL Shading language) to shaders of the GPU

https://github.com/glium/glium/blob/master/book/tuto-02-triangle.md

As far as I understand, it looks like the content of r#...# is left untouched, it is not interpreted in any way. Hence raw string.