Start learning free

LESSON 8 OF 414 · WELCOME TO RUST

String Concatenation in Rust: Joining Text with +

Lesson Read the full explanation

We can concatenate strings with the plus operator (+). The left side must be an owned String (for example String::from("...")) and the right side a &str.

Here is a program that concatenates the strings "I love coding. " and "It is fun!" and assigns the resulted string to a variable message:

let message = String::from("I love coding. ") + "It is fun!";
println!("{}", message);

Output:

I love coding. It is fun!

Concatenation with variables:

String concatenation is redundant when used with string literals because we already know what the resulted string would be.

For example, in our program, we could have initialized message directly with the bigger string instead of doing concatenation:

let message = "I love coding. It is fun!";
println!("{}", message);

String concatenation is used to dynamically generate messages that can be different depending on context.

For example, I might want to print a specific message about my favorite animal, whatever that is:

let favorite_animal = "parrot";

let message = String::from("My favorite animal is the ") + favorite_animal;

println!("{}", message);

Output:

My favorite animal is the parrot

The value of message will differ if my favorite animal was "dog" or "cat", but it would still make sense.


Concatenating multiple strings:

We can concatenate as many strings as we want in the same line of code by adding a + before each string:

let animal = "parrot";
let name = "Andy";

println!("{}", name.to_string() + ", that's a nice " + animal + " you got there!");

Output:

Andy, that's a nice parrot you got there!

Be careful to add whitespaces and other characters you want in your message


Assignment
Follow the Coding Tutorial and let's practice with string concatenation!


Hint
Look at the examples above if you get stuck.


STEP 1 OF 1
    Ctrl + Enter to check

    RUST · WELCOME TO RUST

    String Concatenation in Rust, explained

    Joining strings with the plus operator

    Concatenation means joining two pieces of text into one longer piece. In Rust you can do it with the + operator, but with a rule that surprises many beginners: the left side must be an owned String, and the right side must be a string slice (&str, such as a literal in double quotes).

    let message = String::from("I love coding. ") + "It is fun!";
    println!("{}", message);
    

    This prints I love coding. It is fun!. String::from(...) creates the owned string on the left, and "It is fun!" is appended to it.

    Why the left side must be a String

    A string literal like "Hello " is a &str: a read-only view of text stored in the program. It can't grow. A String owns a buffer that can be extended. The + operator takes the String on its left, appends the text on its right to that buffer and hands the same String back as the result. So two literals can't be added directly:

    let a = "Hello ";
    let b = "world";
    let c = a + b;
    

    This fails with error[E0369]: cannot add `&str` to `&str`, and the compiler notes that concatenation requires an owned String on the left. Starting from String::from("Hello ") or a.to_string() fixes it.

    The right side is a &str, not a String

    The reverse also trips people up. When both values are Strings, the right one needs a & in front:

    let a = String::from("Hello ");
    let b = String::from("world");
    let c = a + &b;
    println!("{} {}", c, b);
    

    This prints Hello world world. Without the &, the compiler reports mismatched types with expected `&str`, found `String`. With it, b is only borrowed, so it can still be used afterwards, as the last print shows.

    The left side is moved

    The left String is consumed by the operation. Its buffer becomes part of the result, so the original variable can't be used afterwards:

    let a = String::from("Hello ");
    let c = a + "world";
    println!("{}", a);
    

    This does not compile: error[E0382]: borrow of moved value: `a`. Use c from then on, or write a.clone() + "world" if you really need both. Ownership is explained in more detail in a later lesson.

    Concatenating with variables

    Joining string literals is pointless, since you could write the long string directly. Concatenation becomes useful when part of the text comes from a variable:

    let favorite_animal = "parrot";
    
    let message = String::from("My favorite animal is the ") + favorite_animal;
    
    println!("{}", message);
    

    It prints My favorite animal is the parrot. Change the value of favorite_animal and the sentence changes with it.

    Chaining several pieces

    Each + returns a String, which is exactly what the next + needs on its left. So you can chain as many pieces as you like:

    let animal = "parrot";
    let name = "Andy";
    
    println!("{}", name.to_string() + ", that's a nice " + animal + " you got there!");
    

    It prints Andy, that's a nice parrot you got there!. Here name.to_string() turns the &str into the owned String that must start the chain. Spaces are part of the text and Rust adds none, so put them inside the literals yourself.

    Solving the exercise

    The exercise gives you name and language, both &str, and asks for a sentence of the form My name is John Doe and I code in Python. Work from left to right:

    1. Start with an owned string. String::from("My name is "), with the trailing space inside the quotes.
    2. Add name. It is a &str, so it can go on the right of + as it is.
    3. Add the middle text. " and I code in " has a space on both sides, because nothing else will supply them.
    4. Add language. Then give the whole expression to println! as the single argument for "{}".
    let name: &str = "John Doe";
    let language: &str = "Python";
    
    println!("{}", String::from("My name is ") + name + " and I code in " + language);
    

    The output is My name is John Doe and I code in Python.

    Joining numbers into text

    The right side of + must be text, so a number has to be converted first. 5.to_string() makes the string "5", and String::from("x=") + &5.to_string() gives x=5. The & is needed because to_string() returns a String, and the right side must be a &str. Rust accepts &String there because it automatically converts a reference to a String into a &str.

    Other ways to build text

    A long chain of + gets hard to read. Two common alternatives produce the same text:

    • format!("My name is {} and I code in {}", name, language) builds a new String from a template and doesn't move anything.
    • push_str and += append to an existing mut String in place. After let mut s = String::from("ab");, both s.push_str("cd") and s += "ef" grow s, which ends up as abcdef.

    Key takeaways

    • String + &str gives a String. Two &str values can't be added.
    • Start a chain with String::from(...), .to_string() or .to_owned().
    • Put & before a String on the right side.
    • The left String is moved into the result and can't be used again.
    • Spaces and punctuation must be written into the text by you.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free