枚举
类C的枚举类型会在内存里存成整型,且Rust会用最小的能够存放的类型来存。可以用#[repr]指定其内存形式。使用的时候用as进行类型转换也是可以的。但是不能从其它类型转成枚举,只能自己写转换逻辑或者使用crate enum_primitive。
对应结构体,枚举的成员也有三种类型:结构体型,元组型和单元型。
成员的可见性和枚举本身一致。
在内存里,有数据的enum会保存一个小整型作为标签,加上能够容纳最大的成员的内存。标签是给Rust内部用来识别是哪个成员的。但Rust不保证内存结构。
use std::collections::HashMap;enum Json {Null,Boolean(bool),Number(f64),String(String),Array(Vec<Json>),Object(Box<HashMap<String, Json>>),}
上例中使用Box是为了让内存更紧致(compact,压缩,整齐),因为enum在内存里要能放下最大的那个成员,如果不用指针而是放实际的对象,则会占用很大的内存。
在泛型枚举(generic enum)中,像Option
模式
| Pattern type | Example | Notes |
|---|---|---|
| Literal | 100 “name” |
Matches an exact value; the name of a const is also allowed |
| Range | 0 ..= 100 ‘a’ ..= ‘k’ |
Matches any value in range, including the end value |
| Wildcard | _ | Matches any value and ignores it |
| Variable | name mut count |
Like _ but moves or copies the value into a new local variable |
| ref variable | ref field ref mut field |
Borrows a reference to the matched value instead of moving or copying it |
| Binding with subpattern | val @ 0 ..= 99 ref circle @ Shape::Circle { .. } |
Matches the pattern to the right of @, using the variable name to the left |
| Enum pattern | Some(value) None Pet::Orca |
|
| Tuple pattern | (key, value) (r, g, b) |
|
| Array pattern | [a, b, c, d, e, f, g] [heading, carom, correction] |
|
| Slice pattern | [first, second] [first, _, third] [first, .., nth] [] |
|
| Struct pattern | Color(r, g, b) Point { x, y } Card { suit: Clubs, rank: n } Account { id, name, .. } |
|
| Reference | &value &(k, v) |
Matches only reference values |
| Multiple patterns | ‘a’ | ‘A’ | In refutable patterns only (match, if let, while let) |
| Guard expression | x if x * x <= r2 | In match only (not valid in let, etc.) |
匹配结构的时候可以用..省略不关心的字段。
匹配切片的时候不仅匹配值还可以匹配长度,..也可以用来省略元素。
match的值在匹配的分支会转移不能Copy的类型,使用ref可以借用引用,而不转移。
#[derive(Debug)]struct S {a: String,b: String}fn main() {let s = S {a: "1".into(), b: "2".into()};match s {S{ref a, ref b} => println!("{}, {}", a, b),_ => {}}println!("{:#?}", s) // 如果不用ref这里会报错:borrow of partially moved value: `s`}
可见match本身并不会转移,而是在具体的分支才会,但如果match处就借用&s,分支处也不用ref了。(因为有Binding modes,如果match的本身是引用,匹配到变量会自动变成引用)ref mut可以从匹配分支获取可变引用。
匹配条件里的变量是重新声明的,会shadow其它同名的变量。
在match条件后还可以再家if判断来进行更具体的判断,被称为match guard。|可以表示或,在一个条件中匹配其中一个就算匹配。..=用来匹配范围:1..=9,'a'..='z',开区间匹配是不允许的。@用来给匹配赋值s1 @ S{..} =>,x @ 1..=9 =>。
模式匹配还可以用来,定义变量,传递参数,for循环。用来解构struct,tuple和map。用在这些地方的模式只能是irrefutable的,match,if let和while let中可以用refutable的。
