目录
- 结构体的使用
- 输出结果
- 结构体简化创建
- 结构体更新语法
- 元组结构体
- 单元结构体(unit struct)
- 结构体中的引用
- 使用#[derive(Debug)]
- 再次介绍
- 代码综合展示
与元组不同的是,结构体可以为内部的每个字段起一个富有含义的名称,因此无需依赖这些字段的顺序就可以来访问和解析它们。
结构体的使用
// 定义一个结构体 Person
struct Person {
name: String,
age: u32,
}
// 为 Person 结构体实现方法
impl Person {
fn greet(&self) {
println!("Hello, my name is {}.", self.name);
}
}
fn main() {
// 创建一个 Person 结构体实例
let mut person1 = Person {
name: String::from("Alice"),
age: 30,
};
// 修改 Person 结构体字段
// 必须要将结构体实例声明为可变的,才能修改其中的字段,Rust 不支持将某个结构体某个字段标记为可变。
person1.name = String::from("Amy");
// 访问 Person 结构体字段
println!("Name: {}", person1.name);
println!("Age: {}", person1.age);
// 调用 Person 结构体方法
person1.greet();
}
输出结果
结构体简化创建
fn build_user(email: String, username: String) -> User {
User {
email,//当函数参数和结构体字段同名时,可以直接使用缩略的方式进行初始化
username,//当函数参数和结构体字段同名时,可以直接使用缩略的方式进行初始化
active: true,
sign_in_count: 1,
}
}
结构体更新语法
-
..
语法表明凡是我们没有显式声明的字段,全部从user1
中自动获取。 - 需要注意的是
..user1
必须在结构体的尾部使用。
let user2 = User {
email: String::from("another@example.com"),
..user1
};
- 结构体更新语法跟赋值语句
=
非常相像,结果是,username
所有权被转移给了user2
,导致了user1
无法再被使用。 - 把结构体中具有所有权的字段转移出去后,将无法再访问该字段,但是可以正常访问其它的字段。
元组结构体
- 元组结构体在某些情况下比普通结构体更方便,特别是当您只需要一个简单的数据结构来存储几个字段时。元组结构体可以帮助您更清晰地表达代码的意图,并且具有元组的轻量性和灵活性。
- 结构体的字段可以没有名称,这种结构体长得很像元组。
// 定义一个类似元组的结构体 Color,表示颜色
struct Color(i32, i32, i32);
// 定义一个类似元组的结构体 Point,表示三维空间中的点
struct Point(i32, i32, i32);
fn main() {
// 创建一个 Color 结构体实例,表示黑色
let black = Color(0, 0, 0);
// 创建一个 Point 结构体实例,表示原点
let origin = Point(0, 0, 0);
// 访问 Color 结构体的字段
println!("Black: ({}, {}, {})", black.0, black.1, black.2);
// 访问 Point 结构体的字段
println!("Origin: ({}, {}, {})", origin.0, origin.1, origin.2);
}
单元结构体(unit struct)
- 它不包含任何字段。单元结构体的定义非常简单,只是由结构体关键字
struct
后面跟结构体的名称构成,例如:
struct UnitStruct;
- 单元结构体在 Rust 中主要用于表示不需要存储数据的类型,通常用作占位符、类型标记或模块化设计中的辅助类型。
结构体中的引用
- 如果想在结构体中使用一个引用,就必须加上生命周期。
- 生命周期能确保结构体的作用范围要比它所借用的数据的作用范围要小。
使用#[derive(Debug)]
- 如果使用
{}
来格式化输出,那对应的类型就必须实现Display
特征,结构体不默认实现Display
特征。因此下面的代码会报错:
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!("rect1 is {}", rect1);
}
- 如果改为:
println!("rect1 is {:?}", rect1);
// 会提醒我们没有实现debug特征
error[E0277]: `Rectangle` doesn't implement `Debug`
- 正确使用方法:
#[derive(Debug)]// 加上这一个东西
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!("rect1 is {:?}", rect1);
}
再次介绍
- 在
Rust
中,#[derive(Debug)]
是一个非常方便的属性,用于自动实现Debug trait
。Debug trait
是一个用于打印调试信息的trait
,通过实现这个trait
,可以使用println!("{:?}", variable);
这样的方式来输出变量的调试信息,而不需要手动实现Debug trait
的fmt
方法。 -
#[derive(Debug)]
的使用可以简化代码,并让我们更方便地输出结构体、枚举等类型的调试信息。
代码综合展示
// 定义一个结构体 Person
struct Person {
name: String,
age: u32,
}
// 为 Person 结构体实现方法
impl Person {
fn greet(&self) {
println!("Hello, my name is {}.", self.name);
}
}
// 定义一个元组结构体 Point
struct Point(i32, i32);
// 定义一个结构体 Rectangle,并衍生 Debug 特性
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
// 创建一个 Person 结构体实例
let person1 = Person {
name: String::from("Alice"),
age: 30,
};
// 访问 Person 结构体字段
println!("Name: {}", person1.name);
println!("Age: {}", person1.age);
// 调用 Person 结构体方法
person1.greet();
// 创建一个可变 Person 结构体实例
let mut person2 = Person {
name: String::from("Bob"),
age: 25,
};
// 修改 Person 结构体字段
person2.age = 26;
// 创建一个元组结构体实例
let origin = Point(0, 0);
// 创建一个 Rectangle 结构体实例
let rect = Rectangle {
width: 10,
height: 20,
};
// 打印 Rectangle 结构体实例,使用 Debug 特性
println!("{:?}", rect);
}
输出结果:【这个警告实在是不知道怎么修改,明明已经使用println!("{:?}", variable);
了】