结构体
在实例化一个结构体时将它整体标记为可变的,但是 Rust 不允许我们将结构体的某个字段专门指定为可变的。一旦实例可变,那么实例中的所有字段都将是可变的。
Copy struct User {
username : String ,
email : String ,
sign_in_count : u64 ,
active : bool ,
}
Copy #![allow(unused)]
fn main () {
let user1 = User {
email : String :: from ( "someone@example.com" ),
username : String :: from ( "someusername123" ),
active : true ,
sign_in_count : 1 ,
};
}
当函数参数和结构体字段同名时,可以直接使用缩略的方式进行初始化,跟 TypeScript 中一模一样。
Copy #![allow(unused)]
fn build_user (email : String , username : String ) -> User {
User {
email,
username,
active : true ,
sign_in_count : 1 ,
}
}
Copy let user2 = User {
email : String :: from ( "another@example.com" ),
username : String :: from ( "anotherusername567" ),
.. user1
};
..
语法表明凡是我们没有显示声明的字段,全部从 user1
中自动获取。需要注意的是 ..user1
必须在结构体的尾部使用。
值得注意的是:username
所有权被转移给了 user2
,导致了 user1
无法再被使用,但是并不代表 user1
内部的其它字段不能被继续使用。
Copy #![allow(unused)]
fn main () {
struct Color ( i32 , i32 , i32 );
struct Point ( i32 , i32 , i32 );
let black = Color ( 0 , 0 , 0 );
let origin = Point ( 0 , 0 , 0 );
}
Copy #![allow(unused)]
fn main () {
struct AlwaysEqual ;
let subject = AlwaysEqual ;
// 我们不关心 AlwaysEqual 的字段数据,只关心它的行为,因此将它声明为单元结构体,然后再为它实现某个特征
impl SomeTrait for AlwaysEqual {
}
}
如果想在结构体中使用一个引用,就必须加上生命周期,否则就会报错。
{:?},{:#?}
dbg!宏:拿走表达式的所有权,打印出相应的文件名、行号等 debug 信息,最终还会把表达式值的所有权返回 。
当解构一个变量时,可以同时使用 move
和引用模式绑定的方式。当这么做时,部分 move
就会发生:变量中一部分的所有权被转移给其它变量,而另一部分我们获取了它的引用。
在这种情况下,原变量将无法再被使用,但是它没有转移所有权的那一部分依然可以使用,也就是之前被引用的那部分。
枚举
任何类型的数据都可以放入枚举成员中 : 例如字符串、数值、结构体甚至另一个枚举。
Copy enum Message {
Quit ,
Move { x : i32 , y : i32 },
Write ( String ),
ChangeColor ( i32 , i32 , i32 ),
}
fn main () {
let m1 = Message :: Quit ;
let m2 = Message :: Move {x : 1 ,y : 1 };
let m3 = Message :: ChangeColor ( 255 , 255 , 0 );
}
#![allow(unused)]
fn main () {
struct QuitMessage ; // 单元结构体
struct MoveMessage {
x : i32 ,
y : i32 ,
}
struct WriteMessage ( String ); // 元组结构体
struct ChangeColorMessage ( i32 , i32 , i32 ); // 元组结构体
}
从代码规范角度来看,枚举的实现更简洁,代码内聚性更强,不像结构体的实现,分散在各个地方。
Rust 吸取了众多教训,决定抛弃 null
,而改为使用 Option
枚举变量来表述这种结果。
Option 枚举包含两个成员,一个成员表示含有值:Some(T), 另一个表示没有值:None
Copy
#![allow(unused)]
enum Option < T > {
Some ( T ),
None ,
}
其中 T
是泛型参数,Some(T)
表示该枚举成员的数据类型是 T
,换句话说,Some
可以包含任何类型的数据。
只要一个值不是 Option<T>
类型,你就 可以 安全的认定它的值不为空。这是 Rust 的一个经过深思熟虑的设计决策,来限制空值的泛滥以增加 Rust 代码的安全性。
Copy
#![allow(unused)]
fn main () {
fn plus_one (x : Option < i32 >) -> Option < i32 > {
match x {
None => None ,
Some (i) => Some (i + 1 ),
}
}
let five = Some ( 5 );
let six = plus_one (five);
let none = plus_one ( None );
}
plus_one
通过 match
来处理不同 Option
的情况。