Rust is a modern systems programming language focusing on safety and speed. It accomplishes these goals by being memory safe without using garbage collection.
Rust by Example is a collection of examples that illustrate various Rust concepts and the standard libraries. You can also check out the source code for this site.
Be sure to have Rust installed and the docs at hand, and let's start!
在 Rust 中自定義的數(shù)據(jù)類型主要是通過(guò)下面兩個(gè)關(guān)鍵字:
-
struct
: 定義結(jié)構(gòu)體 -
enum
: 定義枚舉類型
常量是用const
和static
這兩個(gè)關(guān)鍵字來(lái)聲明.
1. 結(jié)構(gòu)體
用struct
關(guān)鍵字能夠定義三種不同的結(jié)構(gòu)體:
- 最基本的元組結(jié)構(gòu)體,又叫元組(Tupels)
- 經(jīng)典的類C結(jié)構(gòu)體
- 單元結(jié)構(gòu)體(泛結(jié)構(gòu)體?)沒(méi)有成員
示例
// A unit struct
// 單元結(jié)構(gòu)體(泛結(jié)構(gòu)體?)
struct Nil;
// A tuple struct
// 元組結(jié)構(gòu)體
struct Pair(i32, f64);
// A struct with two fields
// 擁有兩個(gè)成員的結(jié)構(gòu)體
struct Point {
x: f64,
y: f64,
}
// Structs can be reused as fields of another struct
// 結(jié)構(gòu)體能夠作為其它結(jié)構(gòu)體的成員
#[allow(dead_code)]
struct Rectangle {
p1: Point,
p2: Point,
}
fn main() {
// Instantiate a `Point`
// 實(shí)例化一個(gè)點(diǎn)
let point: Point = Point { x: 0.3, y: 0.4 };
// Access the fields of the point
// 訪問(wèn)改點(diǎn)的成員
println!("point coordinates: ({}, {})", point.x, point.y);
// Destructure the point using a `let` binding
// 用 let 分解,同時(shí)得到各成員值
let Point { x: my_x, y: my_y } = point;
let _rectangle = Rectangle {
// struct instantiation is an expression too
// 結(jié)構(gòu)體的實(shí)例化是表達(dá)式,即有返回值
p1: Point { x: my_y, y: my_x },
p2: point,
};
// Instantiate a unit struct
// 實(shí)例化一個(gè)單元結(jié)構(gòu)體
let _nil = Nil;
// Instantiate a tuple struct
// 實(shí)例化一個(gè)元組結(jié)構(gòu)體
let pair = Pair(1, 0.1);
// Destructure a tuple struct
// 結(jié)構(gòu)一個(gè)元組結(jié)構(gòu)體
let Pair(integer, decimal) = pair;
println!("pair contains {:?} and {:?}", integer, decimal);
}
結(jié)果
point coordinates: (0.3, 0.4)
pair contains 1 and 0.1
2.枚舉
enum
關(guān)鍵字能夠創(chuàng)建包含不同數(shù)據(jù)類型的類型.對(duì)struct
有效的類型同樣對(duì)enum
有效.
示例
// An attribute to hide warnings for unused code.
// 對(duì)未使用的代碼忽略警告
#![allow(dead_code)]
// Create an `enum` to classify someone. Note how both names
// and type information together specify the variant:
// 用` enum `創(chuàng)建一個(gè)"人"的類, 注意,名字和類型信息都是指特定的數(shù)據(jù)類型:
// `Skinny != Fat` and `Height(i32) != Weight(i32)`. Each
// is different and independent.
// `Skinny != Fat` and `Height(i32) != Weight(i32)`. 他們是不同的,獨(dú)立的.
enum Person {
// An `enum` may either be `unit-like`,
// 一個(gè)枚舉可以是 單元
Skinny,
Fat,
// like tuple structs,
// 元組
Height(i32),
Weight(i32),
// or like structures.
// 結(jié)構(gòu)體
Info { name: String, height: i32 }
}
// A function which takes a `Person` enum as an argument and
// returns nothing.
// 一個(gè)需要傳入 `Person`枚舉作為參數(shù),無(wú)返回值的函數(shù).
fn inspect(p: Person) {
// Usage of an `enum` must cover all cases (irrefutable)
// so a `match` is used to branch over it.
// 枚舉的使用必須覆蓋所有條目,所以` match `里面有它所有的分支.
match p {
Person::Skinny => println!("Is skinny!"),
Person::Fat => println!("Is fat!"),
// Destructure `i` from inside the `enum`.
// 從枚舉中分解出 ` i `
Person::Height(i) => println!("Has a height of {}.", i),
Person::Weight(i) => println!("Has a weight of {}.", i),
// Destructure `Info` into `name` and `height`.
// 分解出` Info ` 到 `name` and `height`.
Person::Info { name, height } => {
println!("{} is {} tall!", name, height);
},
}
}
fn main() {
let person = Person::Height(18);
let danny = Person::Weight(10);
// `to_owned()` creates an owned `String` from a string slice.
// `to_owned()`創(chuàng)建字符串切片的`String`類型.
let dave = Person::Info { name: "Dave".to_owned(), height: 72 };
let john = Person::Fat;
let larry = Person::Skinny;
inspect(person);
inspect(danny);
inspect(dave);
inspect(john);
inspect(larry);
}
結(jié)果
Has a height of 18.
Has a weight of 10.
Dave is 72 tall!
Is fat!
Is skinny!
2.1 use
用use
關(guān)鍵字來(lái)代替獲取.
// An attribute to hide warnings for unused code.
// 對(duì)未使用的代碼忽略警告
#![allow(dead_code)]
enum Status {
Rich,
Poor,
}
enum Work {
Civilian,
Soldier,
}
fn main() {
// Explicitly `use` each name so they are available without
// manual scoping.
// ` use `帶上每一個(gè)名字
use Status::{Poor, Rich};
// Automatically `use` each name inside `Work`.
// 自動(dòng)` use `所有名字
use Work::*;
// Equivalent to `Status::Poor`.
// 等價(jià)于`Status::Poor`
let status = Poor;
// Equivalent to `Work::Civilian`.
// 等價(jià)于`Work::Civilian`
let work = Civilian;
match status {
// Note the lack of scoping because of the explicit `use` above.
// 注意不需要帶上域(`Status`),因?yàn)槊鞔_地使用了`use`
Rich => println!("The rich have lots of money!"),
Poor => println!("The poor have no money..."),
}
match work {
// Note again the lack of scoping.
// 同樣不用帶上域(`Work`)
Civilian => println!("Civilians work!"),
Soldier => println!("Soldiers fight!"),
}
}
結(jié)果
The poor have no money...
Civilians work!
2.2. 類C枚舉
enum
同樣可以作為C中的枚舉類型使用.
// An attribute to hide warnings for unused code.
// 對(duì)未使用的代碼忽略警告
#![allow(dead_code)]
// enum with implicit discriminator (starts at 0)
//
enum Number {
Zero,
One,
Two,
}
// enum with explicit discriminator
enum Color {
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
}
fn main() {
// `enums` can be cast as integers.
println!("zero is {}", Number::Zero as i32);
println!("one is {}", Number::One as i32);
println!("roses are #{:06x}", Color::Red as i32);
println!("violets are #{:06x}", Color::Blue as i32);
}
結(jié)果
zero is 0
one is 1
roses are #ff0000
violets are #0000ff
2.3 測(cè)試用例:鏈表
枚舉比較常見(jiàn)用來(lái)創(chuàng)建鏈表.
示例
use List::*;
enum List {
// Cons: Tuple struct that wraps an element and a pointer to the next node
Cons(u32, Box<List>),
// Nil: A node that signifies the end of the linked list
Nil,
}
// Methods can be attached to an enum
impl List {
// Create an empty list
fn new() -> List {
// `Nil` has type `List`
Nil
}
// Consume a list, and return the same list with a new element at its front
fn prepend(self, elem: u32) -> List {
// `Cons` also has type List
Cons(elem, Box::new(self))
}
// Return the length of the list
fn len(&self) -> u32 {
// `self` has to be matched, because the behavior of this method
// depends on the variant of `self`
// `self` has type `&List`, and `*self` has type `List`, matching on a
// concrete type `T` is preferred over a match on a reference `&T`
match *self {
// Can't take ownership of the tail, because `self` is borrowed;
// instead take a reference to the tail
Cons(_, ref tail) => 1 + tail.len(),
// Base Case: An empty list has zero length
Nil => 0
}
}
// Return representation of the list as a (heap allocated) string
fn stringify(&self) -> String {
match *self {
Cons(head, ref tail) => {
// `format!` is similar to `print!`, but returns a heap
// allocated string instead of printing to the console
format!("{}, {}", head, tail.stringify())
},
Nil => {
format!("Nil")
},
}
}
}
fn main() {
// Create an empty linked list
let mut list = List::new();
// Append some elements
list = list.prepend(1);
list = list.prepend(2);
list = list.prepend(3);
// Show the final state of the list
println!("linked list has length: {}", list.len());
println!("{}", list.stringify());
}
結(jié)果
linked list has length: 3
3, 2, 1, Nil