本文参考rust社区中文文档https://rustwiki.org/zh-CN/book/ch05-01-defining-structs.html,https://rustwiki.org/zh-CN/book/ch10-03-lifetime-syntax.html
文章目录
1. 结构体整体感知
rust结构体可以类比于其他面向对象语言的类、结构体,其中的每一个属性域的值通过赋值的方式初始化,进而初始化整个结构体。结构体中的引用类型数据需要符合引用的安全要求。
2. 结构体定义
结构体的定义使用struct
字段进行定义。
struct StructName{
field1: type1,
field2: type2,
field3: type3,
...
}
或者也可以构建没有字段的结构体。
struct StructName(type1,type2,type3,...)
一下提到的结构体的初始化方式均以有字段名称的为例。
3. 结构体的初始化方式
以文档中的User结构体为例,结构体的命名一般以camel方式即首字母大写的驼峰。
struct User{
username: String,
email: String,
sign_in_count: u64,
active: bool,
};
3.1 直接初始化
let user = User{
username: String::from("username"),
email: String::from("xxxx@xx.xx"),
sign_in_count: 1,
active: true,
};
3.2 简化初始化
对于具有相同名称的变量名可以直接复制不需要使用key:value
方式。
let username = Stirng::from("username");
let email = Stirng::from("xxxx@xx.xx");
let user = User{
email,
username,
sign_in_count:1,
active: true,
};
3.3 通过别的结构体创建
在很多情况下,一份数据的某个或者某几个字段需要修改并备份,但是其余的绝大部分并不需要修改并备份(也可以理解为,这组数据的大部分字段的值是相同的,但是只有少部分字段是不同的),这时候可用通过结构体的更新语法进行创建,即使用..其他结构体
的方式创建。
let user1 = {
username: String::from("username1"),
email: String::from("xxxx@xx.xx1"),
sign_in_count: 1,
active: true,
};
let user2 = {
username: String::from("username2");
email: String::from("xxxx@xx.xx2"),
..user1 // 注意此处的..语法
};
4. 结构体的可变性
rust结构体不允许单独指定某个字段是否为可变,只能整体指定即let mut user = User{...};
。
5. 结构体中数据的所有权
对于一个域内需要一个或多个引用作为输入、一个引用作为输出的域如方法,需要标注引用的生命周期。'生命周期名称
的方式,其中生命周期名称使用小写表示,默认为'a
。生命周期需要直接跟在&
之后,且与类型空开,即&'生命周期名称 类型名称
。为解决以上问题需要对输入的引用以及输出的引用标明生命周期,输出的生命周期需要是输入的生命周期中的一个,以进行使用。
如下举例:
fn f<'a,'b>(x: &'a i32, y: &'b i32) -> &'a i32{
...
}
struct Data<'a,'b>{
x: &'a i32,
y: &'b i32,
}
但是为了简略生命周期写法,有三条规则下可以省略生命周期
- 输入参数的引用生命周期各不相同,且无输出引用
- 输入参数只有一个引用,输出最多为一个引用。
- 有多个输入的引用但是其中一个是
&self
或者&mut self
类似的也适用于结构体的定义,可以自行推导。
6. 结构体的方法
结构体可以添加一些方法,使用impl
字段进行添加。
struct Data{
x: i32,
y: i32,
}
impl{
fn l2_2(&self) -> i32{ //使用 &self参数调用自身属性,或者&mut self,*
self.x**2 + self.y ** 2
}
fn new() -> Data{ //无&self、&mut self字段,可以理解为静态方法,需要通过::来调用, Data::new()
Data{
x: 0,
y: 0
}
}
}
一个结构体的impl
块可以有多个。