Печатные типы в стандартной библиотеке Rust

Beginner

This tutorial is from open-source community. Access the source code

Введение

В этом практическом занятии объясняется, что для использования функциональности форматирования std::fmt типы должны иметь реализацию для печати, которая может быть автоматически предоставлена для типов в библиотеке std. Для других типов можно использовать трейт fmt::Debug, чтобы обеспечить возможность печати. Трейт fmt::Debug упрощает реализацию типов, которые можно печатать, в то время как для fmt::Display требуется вручную реализовать методы. Трейт fmt::Debug позволяет любым типам получить реализацию для печати, и то же самое относится к использованию {:?} для типов библиотеки std. В практическом занятии также рассматривается использование {:?} для печати и приводится пример его использования для печати различных типов. Кроме того, вводится концепция "красивой печати" с использованием {:#?}, которая позволяет более элегантно представлять структуры данных. Наконец, упоминается, что можно вручную реализовать fmt::Display, чтобы иметь контроль над отображением типов.

Примечание: Если практическое занятие не задает имя файла, вы можете использовать любое имя, которое хотите. Например, вы можете использовать main.rs, скомпилировать и запустить его с помощью команд rustc main.rs &&./main.

Debug

Все типы, которые хотят использовать функциональность форматирования std::fmt, должны иметь реализацию для печати. Автоматические реализации предоставляются только для типов, таких как в библиотеке std. Все остальные типы должны быть реализованы вручную каким-то образом.

Трейт fmt::Debug делает это очень простым. Все типы могут derive (автоматически создать) реализацию fmt::Debug. Это не так для fmt::Display, которая должна быть реализована вручную.

// Эта структура не может быть напечатана ни с использованием `fmt::Display`,
// ни с использованием `fmt::Debug`.
struct UnPrintable(i32);

// Атрибут `derive` автоматически создает реализацию,
// необходимую для печати этой `struct` с использованием `fmt::Debug`.
#[derive(Debug)]
struct DebugPrintable(i32);

Все типы библиотеки std также автоматически могут быть напечатаны с использованием {:?}:

// Создаем реализацию `fmt::Debug` для `Structure`. `Structure`
// - это структура, содержащая единственное поле типа `i32`.
#[derive(Debug)]
struct Structure(i32);

// Помещаем `Structure` внутрь структуры `Deep`. Также делаем ее печатаемой.
#[derive(Debug)]
struct Deep(Structure);

fn main() {
    // Печать с использованием `{:?}` похожа на печать с использованием `{}`.
    println!("{:?} months in a year.", 12);
    println!("{1:?} {0:?} is the {actor:?} name.",
             "Slater",
             "Christian",
             actor="actor's");

    // `Structure` печатаема!
    println!("Now {:?} will print!", Structure(3));

    // Проблема с `derive` заключается в том, что нет контроля над тем,
    // как будут выглядеть результаты. Что если я хочу, чтобы это было просто `7`?
    println!("Now {:?} will print!", Deep(Structure(7)));
}

Таким образом, fmt::Debug определенно делает тип печатаемым, но жертвует некоторой элегантностью. Rust также предоставляет "красивую печать" с использованием {:#?}.

#[derive(Debug)]
struct Person<'a> {
    name: &'a str,
    age: u8
}

fn main() {
    let name = "Peter";
    let age = 27;
    let peter = Person { name, age };

    // Красивая печать
    println!("{:#?}", peter);
}

Можно вручную реализовать fmt::Display, чтобы контролировать отображение.

Резюме

Поздравляем! Вы завершили практическое занятие по Debug. Вы можете выполнить больше практических занятий в LabEx, чтобы улучшить свои навыки.