前言#
昨天我们学了rust所有权相关的知识,今天我们继续往下学
struct#
啥是struct?
简单地说就是一个自定义数据类型,你可以把一些相关联的数据放到同一个block中。相信各位前端大佬已经猜到是长啥样了。
定义和实例化structs#
我们直接来看下如何定义一个structs,这里我下面就直接叫结构体了
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
} 没错,长得比较像一个对象,或者说是一个类(ts中的类)。
和元组[3]类似,结构体允许存在多种不同类型的字段,而不同点是结构体需要定义每个字段的名字。
这就意味着结构体会比元组方便,因为字段是需要命名的,那么在实例化以后可以直接通过名字获取字段数据,而不是元组中解构全部或者需要确定元素的位置通过下标获取的方式。
规范是这样的:
struct 结构体名字首字母大写驼峰命名 { key名字小写_多词下划线分隔: 类型, }struct是声明的关键字
结构体的名字以及括号里的字段尽量是有关联的,这是一种好的开发约束。
那要如何使用这个结构体呢?和js差不多,都是创建一个实例。
fn main() {
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
}创建时需要给字段赋值。
实例化时结构体中不会强制要求字段顺序一致,但是必须要将所有字段都写出。

改动其中一个字段的数据和其他语言一样用:点表示法(dot notation)。比如:
let mut user = User {
active: false,
email: String::from("123@qq.com"),
username: String::from("dan"),
sign_in_count: 1
};
user.active = true;当然,结构体必须声明为mut变量,不然还是会报错。
有一点需要注意,如果声明了mut那就意味着实例中的所有字段都是可变的,不存在其中一个可变其中一个不可变的情况。
字段简写#
和js中的一样,如果字段名和赋值给字段的变量名一样,可以直接简写。比如:
fn build_user(email: String, username: String) -> User {
User {
email,
username,
active: true,
sign_in_count: 1,
}
}另外,和js类似的还有解构运算符,在rust中用..而非...
fn main() {
let mut user = User {
active: false,
email: String::from("123@qq.com"),
username: String::from("dan"),
sign_in_count: 1
};
let mut user2 = User {
username: String::from("jack"),
..user
};
}
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}不过有一点需要注意,那就是js中后面的会覆盖前面的数据,而在rust中并不会这样做,如果该字段已经存在赋值,那就不会覆盖。

tuple struct#
元组结构体,来看下如何声明和使用。
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}一目了然,就不多说了。
有一点需要注意的是既然是tuple,那就可以使用下标获取元素。但是解构不行,会报错。

类单元结构体(unit-like struct)#
类似空元祖
struct AlwaysEqual;
fn main() {
let subject = AlwaysEqual;
}至于在那里会需要,以后会说到,这里就不说了,是和trait概念相关的。
结构体的数据所有权#
你应该发现了上面实例中我们使用的字符串类型是String而非字符串切片&str,为什么呢?其实是故意的,因为这样做使得struct User拥有了字段的所有权。
只有结构体里面的字段数据都是数据的拥有者时,这个结构体也就是这些个数据的拥有者。
当然,并没有卡死。还是允许的,比如:
struct User {
active: bool,
username: &str,
email: &str,
sign_in_count: u64,
}
fn main() {
let user1 = User {
email: "someone@example.com",
username: "someusername123",
active: true,
sign_in_count: 1,
};
} 
但是需要声明生命周期,至于啥是生命周期,后面再说。
果然冬天就是啥都不想干呢,尤其是周末,一直躺到下午四点才起床~
明天又要去上班了,好烦。
参考#
- ^rust-struct https://doc.rust-lang.org/book/ch05-00-structs.html#using-structs-to-structure-related-data
- ^rust-define-and-instantiate-structs https://doc.rust-lang.org/book/ch05-01-defining-structs.html#defining-and-instantiating-structs
- ^rust-tuple https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
发布于 2022-12-04 22:24・IP 属地广东
