Skip to main content

Rust 生命周期参数及Trait的说明

Rust
KIGA
Author
KIGA
This is a personal blog, intended for sharing.
use std::fmt;

// 结构体实现了 Display trait, 和实现 Debug trait.
// 如果没有实现 Debug trait, 那么就不能使用 {:?} 格式化输出.
// 如果没有实现 Display trait, 那么就不能使用 {} 格式化输出.

// #[derive(Debug)]
struct User<'a,'b> {
    active: bool,
    username: &'a str,
    email: &'b str,
    sign_in_count: u64,
}

// 定义了一个 impl 块,用于为 User 结构体实现 fmt::Display trait。
// 'a 和 'b 是生命周期参数,用于指定 User 结构体中的引用的生命周期。
impl<'a, 'b> fmt::Display for User<'a, 'b> {
    // 定义了一个 fmt 方法,它接收一个 &self 参数和一个 &mut fmt::Formatter 参数,并返回一个 fmt::Result 类型的结果。
    // &self 参数表示当前实例的引用,&mut fmt::Formatter 参数表示格式化器,用于将格式化的字符串写入到输出流中。
    //  <'_> 是一个生命周期参数,用于指定格式化器的生命周期。'_ 表示一个匿名生命周期
    // 它表示格式化器的生命周期与其引用的值的生命周期相同。这样做的好处是可以避免手动指定生命周期,从而简化代码。
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // 使用 write! 宏将格式化的字符串写入到输出流中。
        write!(
            // f 参数表示格式化器,"User {{ active: {}, username: {}, email: {}, sign_in_count: {} }}" 是格式化字符串
            f,
            "User {{ active: {}, username: {}, email: {}, sign_in_count: {} }}",
            // self.active、self.username、self.email 和 self.sign_in_count 是要格式化的值。
            self.active, self.username, self.email, self.sign_in_count
        )
    }
    // fmt::Result 类型是一个枚举类型,它有两个变体:Ok(()) 和 Err(fmt::Error)。
    // Ok(()) 表示格式化操作成功,而 Err(fmt::Error) 表示格式化操作失败,并包含一个 fmt::Error 类型的错误信息。

    // <> 符号表示泛型参数,用于指定类型或生命周期的参数。泛型参数可以在函数、结构体、枚举、trait 等 Rust 语言结构中使用。
    /*
    // 定义一个泛型函数,它接收一个 T 类型的参数,并返回一个 T 类型的值。
    fn identity<T>(x: T) -> T {
        x
    }

    // 定义一个泛型结构体,它包含一个 T 类型的字段。
    struct Container<T> {
        value: T,
    }

    // 定义一个泛型 trait,它包含一个 T 类型的方法。
    trait MyTrait<T> {
        fn do_something(&self, x: T) -> T;
    }
    */
}

/*
error[E0277]: `User<'_, '_>` doesn't implement `Debug`
  --> test.rs:29:22
   |
29 |     println!("{:?}", user1)
   |                      ^^^^^ `User<'_, '_>` cannot be formatted using `{:?}`
   |
   = help: the trait `Debug` is not implemented for `User<'_, '_>`
   = note: add `#[derive(Debug)]` to `User<'_, '_>` or manually `impl Debug for User<'_, '_>`
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `User<'_, '_>` with `#[derive(Debug)]`
   |
2  + #[derive(Debug)]
3  | struct User<'a,'b> {
   |

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
*/

impl<'a, 'b> fmt::Debug for User<'a, 'b> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "User {{ active: {}, username: {}, email: {}, sign_in_count: {} }}",
            self.active, self.username, self.email, self.sign_in_count
        )
    }
}

fn main() {

    let user_name = "someusername123";
    let email = "someone@example.com";
    let user1 = User {
        active: true,
        username:&user_name,
        email: &email,
        sign_in_count: 1,
    };

    // 未实现fmt::Debug trait, 不能使用 {:?} 格式化输出.
    println!("{:?}", user1);
    // 未实现fmt::Display trait, 不能使用 {} 格式化输出.
    println!("{}", user1);
}
// 简单实现trait, 没有实现trait的方法, 会报错.

// rustc --explain E0277
// E0277: the trait bound `{integer}: Foo` is not satisfied

// // here we declare the Foo trait with a bar method
// trait Foo {
//     fn bar(&self);
// }

// // we now declare a function which takes an object implementing the Foo trait
// fn some_func<T: Foo>(foo: T) {
//     foo.bar();
// }

trait Foo {
    fn bar(&self);
}

// we implement the trait on the i32 type
impl Foo for i32 {
    fn bar(&self) {}
}

fn some_func<T: Foo>(foo: T) {
    foo.bar(); // we can now use this method since i32 implements the
               // Foo trait
}

fn main() {
	some_func(5i32); // ok!
}