Skip to Content
Course content

122: String Formatting with format! Macro

Click on the "Edit" button in the top corner of the screen to edit your slide content.

A few years ago, I was reviewing a PR from a developer who was building a custom logging system for a high-frequency trading platform. He had written a line of code to generate a transaction ID string that looked something like this: let id = String::from("TXN-") + &timestamp.to_string() + &"-" + &user_id.to_string() + &"-" + &session_id.to_string();. It was a complete eyesore. Not only was it hard to read, but it was inefficient, creating multiple intermediate string allocations just to get one final result. I told him right then: "Stop fighting the types and just use the format! macro."

Creating Strings without the Concatenation Headache

If you've used println!, you already know 90% of how format! works. The only difference is that while println! sends the formatted text to the console, format! returns a String. It's your primary tool for building dynamic strings that you need to store in a variable, pass into a function, or return from a method.

let user = "Alice";
let login_attempts = 3;
let message = format!("User {} has failed login {} times.", user, login_attempts);
// message is now a String: "User Alice has failed login 3 times."

I prefer this approach because it separates the structure of the string from the data. It's much easier to scan a template and see what the final output will look like than to mentally parse a chain of plus signs and to_string() calls.

Controlling the Layout with Formatting Specifiers

Sometimes you need more than just a placeholder. If you're building a CLI tool or a report, you likely need things to line up. Rust gives you a powerful set of formatting specifiers inside the curly braces. For example, if you're displaying a price, you don't want 12.5; you want 12.50.

let price = 12.5;
let formatted_price = format!("Total cost: ${:.2}", price); 
// Result: "Total cost: $12.50"

You can also handle padding and alignment. If you're printing a list of IDs and want them all to be the same width—say, 5 characters, padded with zeros—you can use {:05}. I've found this incredibly useful when generating filenames for sequential backups or log rotations where alphabetical sorting depends on the numbers having the same number of digits.

Reusing Arguments and Named Placeholders

In more complex strings, you might find yourself needing the same variable three or four times. Instead of passing the same variable into the macro repeatedly, you can use positional arguments. By putting a number inside the braces, you tell Rust which argument to use (starting at 0).

let first = "Hydrogen";
let second = "Helium";
let sequence = format!("{0}, {1}, then {0} again", first, second);
// Result: "Hydrogen, Helium, then Hydrogen again"

But if the list of arguments gets long, numbers become confusing. That's where named arguments come in. This is the cleanest way to handle long templates. You define the name inside the brace and assign the value at the end of the macro call. It makes the code self-documenting.

let report = format!(
    "System Status: {status} | Uptime: {uptime}s | Load: {load}%",
    status = "Healthy",
    uptime = 3600,
    load = 14.2
);



📋 Practical Task

Build a Digital Invoice Line Generator

You are building a billing module for a freelance platform. Instead of printing directly to the screen, you need to create a function that generates a single, perfectly formatted string for an invoice line item.

Write a function generate_invoice_line(item_name: &str, quantity: u32, unit_price: f64) -> String that returns a string based on these requirements:

  • The item_name should be left-aligned and occupy exactly 20 characters.
  • The quantity should be right-aligned and occupy 5 characters.
  • The unit_price must be formatted to exactly 2 decimal places.
  • The final string should look like this: "Item: [Name] Qty: [Qty] Price: $[Price]"

Example Output:
generate_invoice_line("Rust eBook", 2, 19.99) should return:
"Item: Rust eBook Qty: 2 Price: $19.99"

Rating
0 0

There are no comments for now.

to be the first to leave a comment.