Макросы вывода
Функция печати (вывода) в Rust реализована набором макросов из модуля std::fmt. Рассмотрим популярные макросы:
format!:записать отформатированный текст в строкуprint!:вывести содержимое в консоль (стандартный вывод)println!:аналогprint!, автоматически добавляет перевод строки в концеeprint!:вывести содержимое в стандартный поток ошибокeprintln!:аналогeprint!, автоматически добавляет перевод строки в конце
Все макросы с окончанием ln добавляют символ перевода строки, после вывода курсор переходит на новую строку.
Префикс e — сокращение от error, используется для вывода сообщений об ошибках
Все перечисленные макросы используют одинаковый синтаксис форматирования, и Rust проверяет корректность кода форматирования на этапе компиляции.
Примеры использования
Базовый заполнитель {}
{} — универсальный заполнитель, последовательно заменяется переданными аргументами, автоматически преобразуясь в строку для вывода.
fn main() {
println!("{} days", 31);
// Вывод:31 days
}Code language: JavaScript (javascript)
Позиционные аргументы
Внутри {} указывается числовой индекс (отсчет с 0), чтобы вручную выбрать нужный аргумент; поддерживается повторное использование и перестановка порядка аргументов.
fn main() {
println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob");
// Вывод:Alice, this is Bob. Bob, this is Alice
}Code language: JavaScript (javascript)
Как видно из примера, индексы аргументов не обязаны идти по порядку 0 1 2…, их можно переставлять. Переданные аргументы «Alice», «Bob» имеют индексы 0 и 1 соответственно.
Именованные аргументы
Если работа с индексами кажется неочевидной, используйте «именованные аргументы»: в форматирующей строке пишите {имя_аргумента}, при вызове передавайте значения в формате имя_аргумента=значение. Порядок передачи не важен, читаемость кода выше.
fn main() {
println!("{subject} {verb} {object}",
object="the lazy dog",
subject="the quick brown fox",
verb="jumps over");
// Вывод:the quick brown fox jumps over the lazy dog
}Code language: JavaScript (javascript)
По сути вы присваиваете имена передаваемым значениям, после чего в форматирующей строке обращаетесь к ним через {имя_аргумента} — это гораздо нагляднее.
Форматирование систем счисления(:спецификатор)
После двоеточия : внутри заполнителя указывается символ формата, чтобы преобразовать число в двоичную, восьмеричную, шестнадцатеричную и другие системы счисления.
:b:двоичная система:o:восьмеричная система:x:шестнадцатеричная система (маленькие буквы)
fn main() {
println!("Десятичная: {}", 69420); // 69420
println!("Двоичная: {:b}", 69420); // 10000111100101100
println!("Восьмеричная: {:o}", 69420); // 207454
println!("Шестнадцатеричная:{:x}", 69420); // 10f2c
}Code language: JavaScript (javascript)
Ширина, выравнивание и заполнение
1 Выравнивание вправо(>ширина)
{:>n} означает общую ширину вывода n, содержимое выравнивается вправо, свободное пространство слева заполняется пробелами.
fn main() {
println!("{number:>5}", number=1);
// Общая ширина 5, слева 4 пробела → Вывод: 1
}Code language: JavaScript (javascript)

2 Выравнивание с заполнением нулями
Перед символом выравнивания добавьте 0, чтобы заполнять свободное место цифрой 0 вместо пробелов.
:0>5:выравнивание вправо, заполнение нулями слева:0<5:выравнивание влево, заполнение нулями справа
fn main() {
println!("{number:0>5}", number=1); // Выравнивание вправо, нули слева → 00001
println!("{number:0<5}", number=1); // Выравнивание влево, нули справа → 10000
}Code language: JavaScript (javascript)
Можно использовать любой другой символ вместо нуля. В примере ниже свободное место слева заполняется большой буквой A
fn main() {
println!("{number:A>5}", number=1); // Выравнивание вправо, заполнение A → AAAA1
println!("{number:A<5}", number=1); // Выравнивание влево, заполнение A → 1AAAA
}Code language: PHP (php)

3 Динамическая ширина(имя_переменной$)
Ширина не прописывается жестко в коде, через имя_переменной$ ссылаемся на внешние именованные аргументы / переменные для динамического регулирования ширины вывода.
То есть ширину можно задавать через переменную, а не фиксировать прямо в коде.
fn main() {
// Способ 1: совместно с именованными аргументами
println!("{number:0>width$}", number=1, width=8);
// Способ 2: прямое обращение к переменным внутри кода (поддерживается Rust 1.58+)
let number: f64 = 1.0;
let width: usize = 8;
println!("{number:>width$}"); // Вывод: 1
}Code language: JavaScript (javascript)

Проверка аргументов на этапе компиляции
Rust на этапе компиляции проверяет совпадение количества заполнителей и переданных аргументов; при нехватке аргументов сразу выдаёт ошибку компиляции.
fn main() {
// 2 заполнителя, но передан только 1 аргумент → компиляция прерывается
println!("My name is {0}, {1} {0}", "Bond");
// Исправление: добавить аргумент "James"
println!("My name is {0}, {1} {0}", "Bond", "James");
}Code language: JavaScript (javascript)

Сообщение компилятора: позиция {1} невалидна, потому что передан лишь один аргумент.
Ошибка: ссылка на несуществующий позиционный аргумент 1 (передан только 1 аргумент)
--> D:\rustdemo\hello.rs:3:29
|
3 | println!("My name is {0}, {1} {0}", "Bond");
| ^
|
= Подсказка: позиционные аргументы нумеруются с 0
Ошибка: компиляция остановлена, всего 1 ошибкаCode language: JavaScript (javascript)
Ограничения форматирования пользовательских типов
По умолчанию конструкция {} работает только с типами, реализующими трейт fmt::Display. Пользовательские структуры этот трейт не реализуют из коробки, прямой вывод через {} вызовет ошибку компиляции.
fn main() {
struct Structure(i32);
// Следующий код не скомпилируется
println!("{}", Structure(3));
}Code language: JavaScript (javascript)

Ошибка[E0277]: структура `Structure` не реализует трейт `std::fmt::Display`
--> D:\rustdemo\hello.rs:4:20
4 | println!("{}", Structure(3));
| -- ^^^^^^^^^^^^ этот тип не может быть выведен стандартным форматтером
| |
| этот форматный аргумент требует реализации трейта Display для типа
Подсказка: у структуры `Structure` нет реализации `std::fmt::Display`
--> D:\rustdemo\hello.rs:2:2
2 | struct Structure(i32);
| ^^^^^^^^^^^^^^^^
Дополнение: в форматирующей строке попробуйте использовать `{:?}` (или `{:#?}` для красивого отладочного вывода)
Компиляция остановлена, найдена 1 ошибка.
Для детализации ошибки выполните команду: rustc --explain E0277Code language: JavaScript (javascript)
* 1 Если нужно вывести структуру — требуется реализовать трейт Display (пока достаточно просто запомнить, разберем позже)
use std::fmt;
struct Structure(i32);
// Реализуем трейт Display для структуры
impl fmt::Display for Structure {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// self.0 обращается к значению i32 внутри кортежной структуры
write!(f, "Число:{}", self.0)
}
}
fn main() {
println!("{}", Structure(3));
}Code language: PHP (php)
* 2 Временная отладка → отладочный формат {:?} / {:#?}
Подходит для отладки разработчика: если не продакшен окружение и нужно просто посмотреть значения внутри структуры, используйте отладочный трейт Debug
Rust по умолчанию реализует отладочный трейт Debug для пользовательских типов, вывод осуществляется через {:?}:
#[derive(Debug)]
#[allow(dead_code)] // убрать предупреждения о неиспользуемом коде/полях
struct Structure(i32);
fn main() {
println!("{:?}", Structure(3));
println!("{:#?}", Structure(3));
}Code language: PHP (php)
* Два ключевых форматирующих трейта модуля std::fmt
Модуль std::fmt содержит множество трейтов для управления отображением текста, два основных:
- fmt::Debug используется с заполнителем
{:?}, предназначен исключительно для вывода в отладочных целях. - fmt::Display используется с заполнителем
{}, выводит контент в стандартном, удобном для обычных пользователей виде.
Встроенные типы стандартной библиотеки уже имеют реализацию обоих трейтов и выводятся напрямую; пользовательские типы не работают без ручной реализации.
При реализации fmt::Display для типа автоматически реализуется трейт ToString, позволяющий преобразовывать данный тип в строку.
#[allow(dead_code)]
#[allow(dead_code)] — атрибут кода, действующий на следующий за ним элемент кода, нужен для скрытия предупреждений «неиспользуемый код».
Рассмотрим пример выше
fn main() {
struct Structure(i32);
// Следующий код не скомпилируется
//println!("{}", Structure(3));
}Code language: JavaScript (javascript)
Строка println!(«{}», Structure(3)); вызывает ошибку, поэтому закомментирована. При запуске такого кода мы получим:
Предупреждение: структура `Structure` никогда не создаётся
--> D:\rustdemo\hello.rs:2:12
|
2 | struct Structure(i32);
| ^^^^^^^^^
|
= примечание: `#[warn(dead_code)]` (часть `#[warn(unused)]`) включено по умолчанию
Выдано 1 предупреждение
Code language: JavaScript (javascript)

Такое предупреждение появляется, потому что строка struct Structure(i32); нигде не используется. Чтобы скрыть предупреждение, добавьте данный атрибут
fn main() {
#[allow(dead_code)]
struct Structure(i32);
// Следующий код не скомпилируется
//println!("{}", Structure(3));
}Code language: PHP (php)
Дробные числа: указание количества знаков после запятой
Определите переменную pi = 3.141592, напишите форматированный вывод с сохранением трех знаков после запятой, вывод:Pi is roughly 3.142.
fn main() {
let pi = 3.141592;
println!("Pi is roughly {:.3}", pi);//3.142
println!("Pi is roughly {0}", pi); //3.141592
}Code language: JavaScript (javascript)