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 中自定義的數據類型主要是通過下面兩個關鍵字:
-
struct
: 定義結構體 -
enum
: 定義枚舉類型
常量是用const
和static
這兩個關鍵字來聲明.
1. 結構體
用struct
關鍵字能夠定義三種不同的結構體:
- 最基本的元組結構體,又叫元組(Tupels)
- 經典的類C結構體
- 單元結構體(泛結構體?)沒有成員
示例
// A unit struct
// 單元結構體(泛結構體?)
struct Nil;
// A tuple struct
// 元組結構體
struct Pair(i32, f64);
// A struct with two fields
// 擁有兩個成員的結構體
struct Point {
x: f64,
y: f64,
}
// Structs can be reused as fields of another struct
// 結構體能夠作為其它結構體的成員
#[allow(dead_code)]
struct Rectangle {
p1: Point,
p2: Point,
}
fn main() {
// Instantiate a `Point`
// 實例化一個點
let point: Point = Point { x: 0.3, y: 0.4 };
// Access the fields of the point
// 訪問改點的成員
println!("point coordinates: ({}, {})", point.x, point.y);
// Destructure the point using a `let` binding
// 用 let 分解,同時得到各成員值
let Point { x: my_x, y: my_y } = point;
let _rectangle = Rectangle {
// struct instantiation is an expression too
// 結構體的實例化是表達式,即有返回值
p1: Point { x: my_y, y: my_x },
p2: point,
};
// Instantiate a unit struct
// 實例化一個單元結構體
let _nil = Nil;
// Instantiate a tuple struct
// 實例化一個元組結構體
let pair = Pair(1, 0.1);
// Destructure a tuple struct
// 結構一個元組結構體
let Pair(integer, decimal) = pair;
println!("pair contains {:?} and {:?}", integer, decimal);
}
結果
point coordinates: (0.3, 0.4)
pair contains 1 and 0.1
2.枚舉
enum
關鍵字能夠創建包含不同數據類型的類型.對struct
有效的類型同樣對enum
有效.
示例
// An attribute to hide warnings for unused code.
// 對未使用的代碼忽略警告
#![allow(dead_code)]
// Create an `enum` to classify someone. Note how both names
// and type information together specify the variant:
// 用` enum `創建一個"人"的類, 注意,名字和類型信息都是指特定的數據類型:
// `Skinny != Fat` and `Height(i32) != Weight(i32)`. Each
// is different and independent.
// `Skinny != Fat` and `Height(i32) != Weight(i32)`. 他們是不同的,獨立的.
enum Person {
// An `enum` may either be `unit-like`,
// 一個枚舉可以是 單元
Skinny,
Fat,
// like tuple structs,
// 元組
Height(i32),
Weight(i32),
// or like structures.
// 結構體
Info { name: String, height: i32 }
}
// A function which takes a `Person` enum as an argument and
// returns nothing.
// 一個需要傳入 `Person`枚舉作為參數,無返回值的函數.
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()`創建字符串切片的`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);
}
結果
Has a height of 18.
Has a weight of 10.
Dave is 72 tall!
Is fat!
Is skinny!
2.1 use
用use
關鍵字來代替獲取.
// An attribute to hide warnings for unused code.
// 對未使用的代碼忽略警告
#![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 `帶上每一個名字
use Status::{Poor, Rich};
// Automatically `use` each name inside `Work`.
// 自動` use `所有名字
use Work::*;
// Equivalent to `Status::Poor`.
// 等價于`Status::Poor`
let status = Poor;
// Equivalent to `Work::Civilian`.
// 等價于`Work::Civilian`
let work = Civilian;
match status {
// Note the lack of scoping because of the explicit `use` above.
// 注意不需要帶上域(`Status`),因為明確地使用了`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!"),
}
}
結果
The poor have no money...
Civilians work!
2.2. 類C枚舉
enum
同樣可以作為C中的枚舉類型使用.
// An attribute to hide warnings for unused code.
// 對未使用的代碼忽略警告
#![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);
}
結果
zero is 0
one is 1
roses are #ff0000
violets are #0000ff
2.3 測試用例:鏈表
枚舉比較常見用來創建鏈表.
示例
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());
}
結果
linked list has length: 3
3, 2, 1, Nil