Rust切片与结构体
一、结构体(struct)
1. 定义
使用 struct 关键字,定义字段名及类型:
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
2. 实例化
创建实例时,需为所有字段赋值:
let user1 = User {
active: true,
username: String::from("张三"),
email: String::from("zhangsan@example.com"),
sign_in_count: 1,
};
- 访问字段:
user1.email
3. 字段初始化简写
当变量名与字段名相同时,可省略字段名:
let username = String::from("李四");
let email = String::from("lisi@example.com");
let user2 = User {
active: true,
username, // 等价于 username: username
email, // 等价于 email: email
sign_in_count: 1,
};
4. 结构体更新语法(..)
基于已有实例快速创建新实例,未显式指定的字段从旧实例中复制(或移动)。
注意:若字段为堆上的类型(如 String),则该字段的所有权会移动到新实例,旧实例将无法再使用该字段。
let user3 = User {
email: String::from("new@example.com"),
..user1 // 其余字段(active, username, sign_in_count)从 user1 获取
};
// 此时 user1.username 的所有权已移至 user3,user1 整体不再可用
5. 元组结构体(Tuple Struct)
没有字段名,只有字段类型,适合用于包装简单类型:
struct Color(u8, u8, u8);
let black = Color(0, 0, 0);
println!("{}", black.0); // 通过索引访问
6. 单元结构体(Unit Struct)
没有字段,行为类似 (),常用于标记类型或实现 trait:
struct MyMarker;
let marker = MyMarker;
7. 打印结构体
-
#[derive(Debug)]作为结构体的外部属性,表示需要打印的调式信息 -
打印时
{:?}和{:#?}表示想使用一种Debug的输出格式 -
Debug1是一个trait,允许我们以一种开发者有帮助的方式打印结构体
-
另一种打印方式是
dbg!宏
8. 方法
方法与函数类似,他们使用fn关键字和名称声明,可以拥有参数和返回值,可以被调用
不同的是,他们在结构体的上下文中被定义,并且它们的第一个参数总是self,它代表调用该方法的结构体实例
struct 结构体 {
字段: 类型,
字段: 类型,
}
impl 结构体名称 {
fn 方法名 (&self) -> 类型 {
// 代码
}
}
-
方法被定义在
impl块中,impl块中的内容都与结构体相关联,所以也叫关联方法 -
&self是self: &self的简写。因为在imql块中,self是imql块的类型的别名。方法第一个参数必须有一个名为self的参数,所以允许简写为&self
二、切片(Slice)
切片允许引用集合中一段连续的元素序列,不拥有所有权,属于借用。
1. 字符串切片(String Slice)
- 通过范围索引
[start..end]获取,end不包含在内。 - 可省略起始或结束索引:
[..5](前5个)、[3..](从索引3到末尾)、[..](全部)。
let s = String::from("hello world");
let hello = &s[0..5]; // "hello"
let world = &s[6..11]; // "world"
let whole = &s[..]; // "hello world"
-
字符串字面量本身就是切片(
&str类型),指向二进制程序中的固定位置。 -
将
String转为字节数组:s.as_bytes(),常用于逐字节处理。
2. 通用切片(其他集合)
切片也适用于数组等连续序列:
let a = [1, 2, 3, 4, 5];
let slice = &a[1..3]; // 类型为 &[i32],包含 [2, 3]