Debug

출력 구현체가 존재하지 않는 타입에는 std::fmt 포맷팅 트레잇을 사용할 수 없습니다. 러스트가 자동으로 구현체를 제공하는 타입은 std 라이브러리 내 타입뿐입니다. 그 외에는 전부 어떤 형태로건 직접 구현해야 합니다.

이 문제는 fmt::Debug 트레잇으로 쉽게 해결할 수 있습니다. 모든 타입은 fmt::Debug 트레잇을 derive 하여 구현체를 자동으로 생성할 수 있습니다. 이는 fmt::Display 트레잇에는 해당되지 않습니다. fmt::Display 트레잇은 반드시 직접 구현해야합니다.


#![allow(unused)]
fn main() {
// 이 구조체는 `fmt::Display`로 출력할 수 없으며,
// `fmt::Debug`로도 출력할 수 없습니다.
struct UnPrintable(i32);

// 다음 `derive` 속성은 이 구조체가 `fmt::Debug`로 출력될 수 있도록
// 구현체를 자동으로 생성합니다.
#[derive(Debug)]
struct DebugPrintable(i32);
}

std 라이브러리 내 타입은 {:?} 로도 출력할 수 있습니다.

// `Structure` 구조체에 `fmt::Debug` 구현체를 derive 합니다.
// `Structure` 구조체는 `i32` 값 하나를 포함합니다.
#[derive(Debug)]
struct Structure(i32);

// `Structure`를 `Deep` 구조체에 집어넣고,
// `Deep` 구조체도 출력 가능하게 만듭니다.
#[derive(Debug)]
struct Deep(Structure);

fn main() {
    // `{:?}` 출력은 `{}`와 비슷합니다.
    println!("1년은 {:?}개월입니다.", 12);
    println!("{1:?} {0:?}는 {actor:?} 이름입니다.",
             "슬레이터(Slater)",
             "크리스찬(Christian)",
             actor="배우");

    // `Structure`는 출력 가능합니다.
    println!("이제 {:?}(을)를 출력할 수 있습니다!", Structure(3));
    
    // `derive`의 문제점은 출력 결과의 형태를 조정할 수 없다는 점입니다.
    // 단순히 `7` 만 출력하려면 어떻게 해야 할까요?
    println!("이제 {:?}(을)를 출력할 수 있습니다!", Deep(Structure(7)));
}

fmt::Debug를 이용해 출력할 수 없던 것을 출력 가능하게 만들어보았습니다. 단정한 형태의 출력을 원하면 {:#?}를 사용해 예쁘게 출력할 수 있습니다.

#[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를 직접 구현해야 합니다.

See also:

attributes, derive, std::fmt, 구조체