什么是struct
struct:结构体,自定义的数据类型,允许我们为相关联的值命名并打包成有意义的组合。
定义struct
使用struct关键字,并为整个struct命名。在{}内为所有字段(Field)定义名称和类型。例:
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
实例化struct
想要使用struct,需要创建struct的实例:
- 为每个字段指定具体的值
- 无须按声明的顺序进行指定
例:
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,//最后的逗号方便增加字段
}
fn main() {
let user = User{
email: String::from("123@123.com"),
username: String::from("jobs"),
active: true,
sign_in_count: 666,
};
println!("{} {} {} {}", user.username, user.email, user.sign_in_count, user.active);
}
实例化时必须初始化全部字段的值,不然编译器会报错。 访问结构体里的某个值使用点标记法,如:user.username 如果要修改结构体实例的某个字段的值,需要将整个实例声明为可变。如:
let mut user = User{
email: String::from("123@123.com"),
username: String::from("jobs"),
active: true, sign_in_count: 666,
};
user.email = String::from("456@666.com");
一旦结构体实例可变,这个实例中所有字段都是可变的。Rust不允许声明结构体内的部分字段可变。
结构体作为函数的返回值
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let user = build_user(String::from("123@123.com"), String::from("jobs"));
println!("{} {} {} {}", user.username, user.email, user.sign_in_count, user.active);
}
fn build_user(username: String, email: String) -> User {
User {
email: email,
username: username,
active: true,
sign_in_count: 666,
}
}
字段初始化简写
当结构体字段值的变量名和字段名相同时,可以简写。例:
fn build_user(username: String, email: String) -> User {
User {
email,
username,
active: true,
sign_in_count: 666,
}
}
结构体更新语法
当基于某个结构体实例来创建一个新实例的时候,可以使用结构体更新语法。例:
fn main() {
let user = build_user(String::from("123@123.com"), String::from("jobs"));
let user1 = User{
active: true,
sign_in_count: 888,
..user
};
println!("{} {} {} {}", user1.username, user1.email, user1.sign_in_count, user1.active);
}
Tuple struct
可以定义类似tuple的struct,叫做tuple struct。Tuple struct整体有个名,但里面的元素没有名。适用于:想给整个tuple取名,并让它不同于其它tuple,而且又不需要为每个元素取名。 定义tuple struct:使用struct关键字,后面是名字以及里面元素的类型。例:
struct Color(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
println!("{} {} {}", black.0, black.1, black.2);
}
Unit-Like Struct(没有任何字段)
可以定义没有任何字段的结构体,叫做Unit-Like Struct(因为于(),单元类型相似)。适用于需要在某个类型上实现某个trait,但是又不想存储任何数据。
结构体数据的所有权
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
这里的username和email使用了String而不是&str,sign_in_count和active又是简单的标量类型,所有该结构体拥有其所有数据的所有权,只要结构体实例有效,那么里面的字段也是有效的。
结构体里允许存放引用字段,但需要使用生命周期。因为引用并不拥有该字段的所有权,一旦该字段作用域小于其结构体实例的作用域,字段被释放时,结构体实例并为释放。那么此实例中的该字段便成了悬垂引用。只要我们通过声明生命周期来保证结构体实例有效时里面的引用也有效,就可以使用存储引用的结构体。