Question
I am learning how string syntax works in Rust, and I want to understand how to create a multiline string. Specifically, what is the correct syntax for a string literal that spans multiple lines in Rust?
Short Answer
By the end of this page, you will understand how multiline string literals work in Rust, how line breaks are preserved, when to use normal string literals versus raw string literals, and how to avoid common mistakes when writing multi-line text.
Concept
In Rust, a string literal can span multiple lines simply by writing the text across lines between double quotes. The newline characters become part of the string.
Rust also supports raw string literals, which are useful when you want to include characters like backslashes (\) or quotes without escaping them.
Why this matters
Multiline strings are useful when you need to store:
- formatted messages
- SQL queries
- JSON samples
- file templates
- usage text for command-line tools
Understanding how Rust treats line breaks and indentation helps you produce the exact string you expect.
Basic idea
A normal multiline string literal looks like this:
let text = "Hello
Rust";
That string contains a newline between Hello and Rust.
You can also write it visually across lines:
let text = "Hello
Rust";
or more commonly:
let text = "Hello
Rust";
In Rust source code, if you physically put the string on separate lines inside the quotes, those line breaks are included in the string.
Raw strings
A raw string starts with r before the quotes:
let text = r"Line 1
Line 2";
In this case, \n is treated as the two characters \ and n, not as a newline.
If you want actual line breaks in a raw string, write actual line breaks:
let text = r"Line 1
Line 2";
or:
let text = r"Line 1
Line 2";
The key rule is:
- Normal strings interpret escapes like
\n - Raw strings do not interpret escapes
Indentation matters
If you indent a multiline string in your code, those spaces usually become part of the string too. That can surprise beginners.
let text = "first line
second line";
Here, second line starts with four spaces inside the actual string.
Mental Model
Think of a Rust string literal like text written onto a sheet of paper.
- If you press Enter, you create a real new line on the paper.
- If you type
\nin a normal string, Rust converts that into pressing Enter for you. - If you type
\nin a raw string, Rust leaves it exactly as typed.
So:
- normal string = "interpret special instructions"
- raw string = "copy text exactly as written"
This is why raw strings are useful for things like file paths, JSON examples, or regular expressions, where lots of backslashes would otherwise be annoying.
Syntax and Examples
Normal multiline string literal
fn main() {
let message = "Hello,
Rust!";
println!("{}", message);
}
This prints:
Hello,
Rust!
The newline between Hello, and Rust! is part of the string.
Using \n in a normal string
fn main() {
let message = "Hello,\nRust!";
println!("{}", message);
}
This produces the same result as the previous example.
Raw multiline string literal
fn main() {
let message = r"Hello,
Rust!";
println!("{}", message);
}
This also contains a real newline because the string itself spans two lines.
Step by Step Execution
Consider this example:
fn main() {
let text = "One
Two";
println!("{}", text);
}
Step by step
- Rust reads the string literal starting at the first
". - It sees
Oneand stores those characters. - It encounters a line break inside the string literal.
- That line break becomes a newline character in the string.
- Rust reads
Twoand adds it after the newline. - The string is assigned to
text. println!("{}", text);prints the string exactly as stored.
Stored value
The value inside text is effectively:
One
Two
Output
One
Two
Now compare with this raw string:
fn main() {
= ;
(, text);
}
Real World Use Cases
Multiline strings appear often in real Rust programs.
Command-line help text
let help = "Usage:
app run
app test
app help";
Useful for CLI tools.
SQL queries
let query = "SELECT id, name
FROM users
WHERE active = true";
This keeps long queries readable.
JSON or config templates
let template = r#"{
"debug": true,
"port": 8080
}"#;
Raw strings reduce escaping.
Email or log messages
let message = "Build finished.
No errors found.
Ready to deploy.";
Useful when formatting human-readable output.
Test data
let input = "apple
banana
orange";
Helpful in unit tests where exact line structure matters.
Real Codebase Usage
In real Rust codebases, developers often choose between normal and raw strings based on what makes the text easiest to read and maintain.
Common patterns
Readable templates
Developers use multiline strings for templates, sample payloads, and embedded documentation.
let request_body = r#"{
"username": "alice",
"active": true
}"#;
Keeping SQL readable
let sql = "SELECT id, email
FROM customers
WHERE subscribed = true";
Exact matching in tests
Tests often compare exact multiline output.
let expected = "line one
line two";
assert_eq!(expected, actual_output);
Validation and error messages
Programs sometimes build user-facing multiline messages for validation errors.
let error_message = "Invalid configuration:
- missing host
- missing port";
Practical advice
- Use normal strings when you want escape sequences like or
Common Mistakes
1. Expecting raw strings to process \n
Broken example:
fn main() {
let text = r"Hello\nRust";
println!("{}", text);
}
This prints:
Hello\nRust
If you want a newline, use a normal string:
let text = "Hello\nRust";
or write an actual newline inside the raw string.
2. Forgetting indentation becomes part of the string
Broken example:
fn main() {
let text = "first line
second line";
println!("{}", text);
}
The spaces before second line are included.
Avoid this by aligning the text intentionally.
3. Escaping quotes unnecessarily in raw strings
Comparisons
| Concept | Syntax | Escapes processed? | Best use |
|---|---|---|---|
| Normal string literal | "Hello\nRust" | Yes | General strings with escapes |
| Multiline normal string | `"Hello | ||
| Rust"` | Yes | Text with real line breaks | |
| Raw string literal | r"Hello\nRust" | No | Text with many backslashes |
Raw string with # | r#"say "hi""# | No | Text containing quotes |
Normal string vs raw string
Cheat Sheet
Quick reference
Normal string
let s = "Hello\nRust";
\nbecomes a newline- escapes are processed
Multiline normal string
let s = "Hello
Rust";
- actual line break is stored in the string
Raw string
let s = r"Hello\nRust";
\nstays as two characters- escapes are not processed
Multiline raw string
let s = r"Hello
Rust";
- actual line break is stored
- backslashes stay literal
Raw string with quotes inside
let = ;
FAQ
How do I write a multiline string in Rust?
You can place the text on multiple lines inside a string literal. The line breaks become part of the string.
Does Rust preserve newlines in a multiline string?
Yes. If the string literal spans lines, those newlines are included in the final value.
What is the difference between a normal string and a raw string in Rust?
A normal string processes escapes like \n. A raw string treats content literally, so \n stays as \n.
How do I include quotes inside a Rust raw string?
Use hashes, such as r#"quoted text"#, so inner double quotes do not end the string.
Why does my multiline string contain extra spaces?
Because indentation inside the quotes is usually part of the string. Align the text carefully.
Should I use \n or actual line breaks?
Use whichever makes the code clearer. \n is useful for short strings; actual line breaks are often easier to read for longer text.
Are multiline string literals and String the same thing in Rust?
No. A string literal has type &str. You can convert it to String if needed, for example with to_string() or .
Mini Project
Description
Build a small Rust program that prints a formatted command-line help message using multiline string literals. This demonstrates how real line breaks are stored, when raw strings are useful, and how formatting affects output.
Goal
Create a Rust program that stores and prints a readable multiline help message and a JSON example.
Requirements
- Create a normal multiline string literal for a help message.
- Print the help message exactly as written.
- Create a raw string literal containing a JSON example.
- Print the JSON example without extra escaping.
Keep learning
Related questions
Accessing Cargo Package Metadata in Rust
Learn how to read Cargo package metadata like version, name, and authors in Rust using compile-time environment macros.
Default Function Arguments in Rust: What to Use Instead
Learn how Rust handles default function arguments, why they are not supported, and practical patterns to achieve similar behavior.
Fixing Rust "linker 'cc' not found" on Debian in WSL
Learn why Rust shows "linker 'cc' not found" on Debian in WSL and how to fix it by installing the required C build tools.