Skip to content

第七节、结构体

定义和实例化

struct User { active: bool, username: String, email: String, sign_in_count: u64, } 结构体的定义和很多流行语言类似。

struct NAME{}
里面是各种字段,实例化过程就是k-v的赋值过程。
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
如果要改变其中的内容,可以实例化为可变的结构体:
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    let mut user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    user1.email = String::from("anotheremail@example.com");
}

也可以定义一个函数来实例化:

fn build_user(email: String, username: String) -> User {
    User {
        email: email,
        username: username,
        active: true,
        sign_in_count: 1,
    }
}
或者写成这样
fn build_user(email: String, username: String) -> User {
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
}
可以继续创建一个user2,user2里面的username使用与user1相同的值
  1 #[derive(Debug)]
  2 struct User {
  3     active: bool,
  4     username: String,
  5     email: String,
  6     sign_in_count: u64,
  7 }
  8 
  9 fn main() {
 10     let mut user1 = User {
 11         email: String::from("someone@example.com"),
 12         username: String::from("someusername123"),
 13         active: true,
 14         sign_in_count: 1,
 15     };
 16 
 17 
 18     let user2 = User {
 19         active: user1.active,
 20         username: user1.username,
 21         email: String::from("another@example.com"),
 22         sign_in_count: user1.sign_in_count,
 23     };
 24 
 25     user1.email = String::from("anotheremail@example.com");
 26     user1.username = String::from("who am I");
 27 
 28     println!("{:?},{:?}",user2,user1)
 29 }
 30 
进一步,还可以这样,user2不同的部分写出来,其他使用user1相同的用..user1来表示,代码如下:
    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };

元祖结构体

元祖结构体没有{},没有字段名字。

fn main() {
    struct Color(i32, i32, i32);
    struct Point(i32, i32, i32);

    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

无字段结构体

fn main() {
    struct AlwaysEqual;

    let subject = AlwaysEqual;
}
这类结构体,没有字段也没有{},()。后面的章节会有详细讲解。

元祖结构体使用示例

fn main() {
    let rect1 = (30, 50);

    println!(
        "The area of the rectangle is {} square pixels.",
        area(rect1)
    );
}

fn area(dimensions: (u32, u32)) -> u32 {
    dimensions.0 * dimensions.1
}

结构体使用示例二、

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        area(&rect1) //引用作为参数,使用的时候站内存小,速度快
    );
}

fn area(rectangle: &Rectangle) -> u32 {
    rectangle.width * rectangle.height
}

结构体的打印

println!("rect1 is {}", rect1);
上面的语句会报错,正确的方法需要添加: #[derive(Debug)],完整代码:
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {:?}", rect1);
}
println里使用的{:?}参数能打印内容,但是排版并不太好看。可以使用{:#?}这样输入更直观. 回到之前的例子,我们打印两种格式做对比:
println!("{:?},{:#?}",user2,user1)
显示结果
User { active: true, username: "someusername123", email: "another@example.com", sign_in_count: 1 },User {
    active: true,
    username: "who am I",
    email: "anotheremail@example.com",
    sign_in_count: 1,
}
也可以使用dbg!宏来打印
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let scale = 2;
    let rect1 = Rectangle {
        width: dbg!(30 * scale),
        height: 50,
    };

    dbg!(&rect1);
}