结构体语法
> 掌握结构体更新语法(..)、元组结构体和单元结构体的使用场景。
结构体更新语法
使用 .. 复制其他字段
rust
▶ Runstruct User {
username: String,
email: String,
active: bool,
sign_in_count: u64,
}
fn main() {
let user1 = User {
username: String::from("user1"),
email: String::from("user1@example.com"),
active: true,
sign_in_count: 1,
};
// 基于 user1 创建 user2
let user2 = User {
email: String::from("user2@example.com"), // 新值
username: String::from("user2"), // 新值
..user1 // 使用 user1 的其他字段(active, sign_in_count)
};
println!("user1: {} ({})", user1.username, user1.email);
println!("user2: {} ({})", user2.username, user2.email);
println!("user2 active: {}", user2.active); // 从 user1 复制
}所有权注意事项
rust
▶ Runstruct User {
username: String, // 不实现 Copy
active: bool, // 实现 Copy
}
fn main() {
let user1 = User {
username: String::from("alice"),
active: true,
};
// 使用 .. 会移动非 Copy 字段
let user2 = User {
username: String::from("bob"),
..user1 // user1.username 被移动
};
// println!("{}", user1.username); // ❌ 错误:已被移动
println!("{}", user1.active); // ✅ 正确:bool 实现 Copy
}三种结构体形式
命名结构体(最常用)
rust
▶ Run// 标准形式,字段有名字
struct Person {
name: String,
age: u32,
}
fn main() {
let p = Person {
name: String::from("Alice"),
age: 25,
};
println!("{} 岁", p.age); // 使用字段名访问
}元组结构体(Tuple Struct)
rust
▶ Run// 有结构体名字,但字段无名字
struct Color(i32, i32, i32); // RGB
struct Point(i32, i32, i32); // XYZ
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
// 使用索引访问
println!("R 值:{}", black.0);
println!("G 值:{}", black.1);
println!("B 值:{}", black.2);
println!("X 值:{}", origin.0);
println!("Y 值:{}", origin.1);
println!("Z 值:{}", origin.2);
// 注意:虽然都是 (0,0,0),但类型不同
// let p: Point = black; // ❌ 错误:类型不同
}元组结构体的使用场景
rust
▶ Run// 场景 1:给元组添加语义
struct PhoneNumber(String);
struct Email(String);
fn main() {
let phone = PhoneNumber(String::from("123-456-7890"));
let email = Email(String::from("test@example.com"));
// 类型安全:不能混用
// let wrong: Email = phone; // ❌ 错误
}
// 场景 2:新类型模式(类型安全)
struct Meters(f64);
struct Feet(f64);
fn print_distance(m: Meters) {
println!("距离:{} 米", m.0);
}
fn main() {
let m = Meters(100.0);
let f = Feet(100.0);
print_distance(m); // ✅ 正确
// print_distance(f); // ❌ 错误:类型不同
}单元结构体(Unit-like Struct)
rust
▶ Run// 没有任何字段
struct AlwaysEqual;
struct Marker;
struct Config;
fn main() {
let marker = Marker; // 只有一个可能的值
// 使用场景:
// 1. 实现 Trait
// 2. 类型标记
// 3. 状态机
}单元结构体的实际用途
rust
▶ Run// 示例:实现 Trait
trait Handler {
fn handle(&self, data: &str);
}
struct LogHandler; // 单元结构体作为标记
impl Handler for LogHandler {
fn handle(&self, data: &str) {
println!("日志:{}", data);
}
}
fn process(handler: &impl Handler, data: &str) {
handler.handle(data);
}
fn main() {
let handler = LogHandler;
process(&handler, "处理数据");
}小结
..struct更新语法:从其他实例复制未指定的字段- 元组结构体:有名字但字段无名字,用于类型安全的"新类型模式"
- 单元结构体:无字段,用于实现 Trait 或类型标记
- 使用
..时注意所有权:非 Copy 字段会被移动
练习题
详见:练习题