定义和实例化结构
结构体类似于 Tuples ,在 “Tuples Type” 一节中讨论,因为两者都包含多个相关值。与元组一样, 结构体的片段可以是不同的类型。与元组不同,在 struct 您将为每条数据命名,以便清楚地了解值的含义。添加这些 names 意味着结构体比 Tuples 更灵活:您不必依赖 按数据的顺序指定或访问实例的值。
要定义结构体,我们输入关键字并命名整个结构体。一个
struct 的名称应该描述数据片段的重要性
组合在一起。然后,在大括号内,我们定义
数据片段,我们称之为 fields。例如,示例 5-1 显示了一个
结构体,用于存储有关用户帐户的信息。struct
要在定义结构后使用它,我们创建该结构的实例 通过为每个字段指定具体值。我们通过以下方式创建实例 说明结构的名称,然后添加包含 key 的大括号: value 对,其中 keys 是字段的名称,values 是 数据。我们不必在 我们在 struct 中声明它们的顺序相同。换句话说, struct definition 就像该类型的通用模板,实例填充 在该模板中,创建该类型的值。为 例如,我们可以声明一个特定的用户,如图 5-2 所示。
要从结构体中获取特定值,我们使用点表示法。例如,到
访问此用户的电子邮件地址时,我们使用 。如果实例为
可变的,我们可以通过使用点表示法并赋值为
特定字段。示例 5-3 展示了如何更改可变实例 field 中的值。user1.email
email
User
请注意,整个实例必须是可变的;Rust 不允许我们标记 只有某些字段是可变的。与任何表达式一样,我们可以构造一个新的 实例作为函数体中的最后一个表达式,以 隐式返回该新实例。
示例 5-4 显示了一个函数,该函数返回一个实例
给定的电子邮件和用户名。该字段获取 的值 ,并且
的值为 。build_user
User
active
true
sign_in_count
1
使用与 struct 相同的名称命名函数参数是有意义的
字段,但必须重复 and 字段名称 和
variables 有点乏味。如果结构体具有更多字段,则重复每个名称
会变得更烦人。幸运的是,有一个方便的速记!email
username
使用 Field init 简写
因为 parameter name 和 struct field name 在
示例 5-4,我们可以使用 field init 速记语法来重写,这样它的行为就完全一样了,但没有 and 的重复,如示例 5-5 所示。build_user
username
email
在这里,我们将创建结构的新实例,该实例具有 field
叫。我们希望将字段的值设置为函数参数中的值。因为 field 和
参数具有相同的名称,我们只需要写 instead
比。User
email
email
email
build_user
email
email
email
email: email
使用 Struct Update 语法从其他实例创建实例
创建包含大部分 的值,但会更改一些值。您可以使用 struct update 语法来执行此作。
首先,在示例 5-6 中,我们展示了如何定期创建新实例,而无需 update 语法。我们为 but 设置了一个新值
否则使用我们在示例 5-2 中创建的相同值。User
user2
email
user1
使用 struct update 语法,我们可以用更少的代码实现相同的效果,因为
如示例 5-7 所示。语法指定其余字段不
explicitly set 的值应与给定实例中的字段相同。..
示例 5-7 中的代码还创建了一个实例,该实例具有
的值不同,但 、 和 字段的值相同。必须到最后
要指定任何剩余字段都应从
中的相应字段,但我们可以选择为 AS 指定值
许多字段,无论
结构的定义。user2
email
username
active
sign_in_count
user1
..user1
user1
请注意,struct update 语法的使用类似于赋值;这是因为
它移动数据,就像我们在“变量和数据交互
移动“部分。在此示例中,创建后不能再作为一个整体使用,因为字段中的 已移动到 中。如果我们为 和 都给出了新值,因此只使用了 中的 和 值,那么 仍然是
创建 后有效。Both 和 都是
实现 trait,因此我们在“Stack-Only
Data: Copy“部分将适用。在此示例中,我们仍然可以使用,因为它的值没有移出。=
user1
user2
String
username
user1
user2
user2
String
email
username
active
sign_in_count
user1
user1
user2
active
sign_in_count
Copy
user1.email
使用不带命名字段的 Tuple 结构创建不同的类型
Rust 还支持看起来类似于元组的结构,称为元组结构。 元组结构具有结构名称提供的附加含义,但没有 与其字段关联的名称;相反,它们只有 领域。当你想给整个元组起个名字时,元组结构很有用 并使元组成为与其他元组不同的类型,并在将每个 field 将是 verbose 或 redundant。
要定义元组结构,请从关键字和结构名称开始
后跟元组中的类型。例如,这里我们定义并使用两个
名为 和 的元组结构 :struct
Color
Point
请注意,和 值是不同的类型,因为它们是
不同元组结构的实例。您定义的每个结构体都是其自己的类型
即使 struct 中的字段可能具有相同的类型。为
例如,采用 type 为 a 的参数的函数不能将 a 作为参数,即使这两种类型都由三个值组成。否则,元组结构实例类似于元组,因为你可以
将它们分解为单独的部分,你可以使用 Followed
通过索引访问单个值。black
origin
Color
Point
i32
.
没有任何字段的类似 Unit 的结构体
您还可以定义没有任何字段的结构体!这些被称为单元状结构,因为它们的行为类似于 ,即
我们在 “元组类型” 一节中提到过。类单元
当你需要在某种类型上实现 trait 但不需要时,结构体可能很有用
具有要存储在类型本身中的任何数据。我们将讨论特征
在第 10 章中。下面是一个声明和实例化 unit 结构体的示例
叫:()
AlwaysEqual
要定义 ,我们使用关键字、我们想要的名称和
然后是分号。无需大括号或圆括号!然后我们可以得到一个
实例:使用
name 定义的,没有任何大括号或圆括号。想象一下以后
我们将为这种类型实现行为,使得 的每个实例 of 始终等于任何其他类型的每个实例,也许等于
具有用于测试目的的已知结果。我们不需要任何数据来
实现该行为!您将在第 10 章中看到如何定义 trait 和
在任何类型的结构体上实现它们,包括类似单元的结构体。AlwaysEqual
struct
AlwaysEqual
subject
AlwaysEqual
结构体数据的所有权
在示例 5-1 的结构体定义中,我们使用了 owned 类型而不是字符串 slice 类型。这是一个经过深思熟虑的选择
因为我们希望这个结构体的每个实例都拥有它的所有数据,并且对于
只要整个结构有效,该数据就有效。User
String
&str
结构也可以存储对某物所拥有的数据的引用 else,但要做到这一点,需要使用 lifetimes,我们将 在第 10 章中讨论。生命周期确保结构体引用的数据 只要结构有效,就有效。假设你尝试存储一个引用 在未指定生命周期的结构体中,如下所示;这不起作用:
编译器会抱怨它需要生命周期说明符:
$ cargo run
Compiling structs v0.1.0 (file:///projects/structs)
error[E0106]: missing lifetime specifier
--> src/main.rs:3:15
|
3 | username: &str,
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
1 ~ struct User<'a> {
2 | active: bool,
3 ~ username: &'a str,
|
error[E0106]: missing lifetime specifier
--> src/main.rs:4:12
|
4 | email: &str,
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
1 ~ struct User<'a> {
2 | active: bool,
3 | username: &str,
4 ~ email: &'a str,
|
For more information about this error, try `rustc --explain E0106`.
error: could not compile `structs` (bin "structs") due to 2 previous errors
在第 10 章中,我们将讨论如何修复这些错误,以便您可以存储
引用,但现在,我们将使用 owned 修复此类错误
类型,而不是引用 .String
&str
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准