디버그

std::fmt의 형식 지정자를 사용하려면 출력할 자료형마다 해당 기능을 구현해야 합니다. 표준(std) 라이브러리의 자료형들에 대해서는 이미 구현이 되어 있지만, 다른 자료형의 경우에는 반드시 직접 구현해야만 합니다.

이때 fmt::Debug 를 이용하면 어렵지 않게 만들 수 있습니다. 어떤 자료형이든 fmt::Debug 을 이용해 파생 구현(derive)을 할 수 있습니다.


#![allow(unused)]
fn main() {
// 아래 구조체는 fmt::Display 나 fmt::Debug 중 어느것으로도 출력할 수 없습니다.
struct UnPrintable(i32);

// derive 속성을 사용하면 fmt::Debug 으로 구조체를 출력할 수 있는 코드가 구현됩니다.
#[derive(Debug)]
struct DebugPrintable(i32);
}

또한 모든 표준(std) 라이브러리의 자료형들은 {:?} 으로 출력이 가능합니다.

// Structure 구조체를 위해 fmt::Debug를 파생 구현합니다. 
// 이 구조체는 i32 한개만 가지고 있습니다.
#[derive(Debug)]
struct Structure(i32);

// 구조체 Deep의 내부에 Structure를 넣습니다. 역시 출력가능하게 만듭니다.
#[derive(Debug)]
struct Deep(Structure);

fn main() {
    // {:?}는  {}와 비슷하게 동작합니다.
    println!("1년에는 {:?}개월이 있다.", 12);
    println!("{1:?} {0:?}는 {actor:?} 이름이다.",
             "강호",
             "송",
             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 를 직접 구현해야만 합니다.

참고:

속성(attributes), 파생 구현(derive), std::fmt, 구조체(struct)