Rust是Mozilla公司發起的一個開源項目。它注重安全、性能和併發,是一種系統級編程語言。Rust是針對多核體系提出的語言,而且吸取一些其餘動態語言的重要特性,好比不須要管理內存,好比不會出現Null指針等等。相比C/C++這些底層語言,rust不但具有底層控制力,且具備良好的高級語言特性,生態系統。Rust一經誕生就被運用於servo瀏覽器內核項目開發,具有實戰經歷。php
首先,在學習rust以前要有這樣的預期:rust不是python,不要指望一個星期迅速掌握。
然而,掌握以後比如光劍在手,能夠盡情釋放原力。python
近期學習rust,是由於rust是支持webassembly的第二個語言,且性能強悍。git
安裝:curl https://sh.rustup.rs -sSf | sh
升級:rustup updategithub
rust支持這些整型數值:i32 u32 i8 u8 i16 u16 isize usize
浮點類型:f32 f64
其餘:char, boolweb
變量聲明以下。類型非必須,不少狀況下編譯器能夠判斷。編程
let a = 1; let a = 1_f32; let a: f32 = 1.0;
rust字符串都是合法的utf-8編碼字符。數組
let s = "Rust❤";
元組是臨時的複合數據類型。瀏覽器
// a tuple of type (i32, f32) let t = (1, 2.0); // 如今有了t.0, t.1
Vector是動態數組,大小可變。安全
let mut v = Vec::new(); v.push(1); v.push(2); let mut v1 = vec![1, 2, 3];
use std::collections::HashMap; let mut score = HashMap::new(); score.insert("Tom", 13); score.insert("Joe", 16);
Battery included!std::collections
下還包括:HashSet
, BTreeMap
, BinaryHeap
, LinkedList
, VecDeque
, BTreeSet
等。併發
3種struct類型。
// unit struct struct Man; let m = Man; // tuple struct struct Man(String, u8); let m = Man(String::from("Tom"), 12); // m.0, m.1; // named-field struct struct Man { name: String, age: u8 } let m = Man { name: String::from("Tom"), age: 12 }; // m.name m.age;
使用impl
塊給struct添加實現。
impl Man { fn new(name: String, age: u8) -> Man { Man { name, age } } fn eat(&mut self, food: String) { // ... } }
&mut self
後面再講,說明eat
是個方法。enum在rust裏獲得了加強,每一個enum值均可以附加其餘數據類型。
rust使用Option
enum解決null引用問題。
enum Option<T> { None, Some(T), }
struct Man { name: String, age: u8, job: Option<String> } let m = Man { name: String::from("Tom"), age: 30, job: Some(String::from("Farmer")) };
rust使用Result
enum做爲異常處理機制,全部可能異常的函數都返回Result
。
enum Result<T, E> { Ok(T), Err(E), }
文件打開函數返回一個Result類型。File::open<P: AsRef<Path>>(path: P) -> Result<File, std::io::Error>
沒有標記mut的變量,不支持修改。
let a = 1; // change to: let mut a = 1; a = 2; // Error: cannot assign twice to immutable variable
rust是基於表達式的語言,不少常見的語法是表達式。(表達式有返回值)
let n = if true { 10 } else { -1 }; fn add(a: i32, b: i32) -> i32 { a + b // 注意沒有分號,加了分號就沒有返回值了。 }
// destrucure tuple let (a, b) = (1, 2); // destrucure tuple struct let m = Man(String::from("Tom"), 12); let Man (name, age) = m; // destrucure named-field struct let m = Man { name: String::from("Tom"), age: 12 }; let Man {name, age} = m;
match是升級版的switch,還支持解構賦值,條件,變量綁定等。match須要窮舉全部可能。能夠用 _
匹配剩下的可能。
match File::open("foo.txt") { Ok(f) => handle_file(f), Err(e) => println!("Something's wrong {}", e), }
if let語句是條件判斷 + 解構。
if let Ok(f) = File::open("foo.txt") { handle_file(f); }
mod: 組織模塊結構
use: 在當前模塊引入
mod jim { pub mod money { pub fn pay() { println!("10$ to you!"); } } } mod tom { pub fn charge() { use jim; jim::money::pay(); } } fn main() { tom::charge(); }
rust-chart ├── main.rs ├── utils.rs └── chart ├── mod.rs └── kline.rs
main.rs
mod utils; mod chart;
chart/mod.rs
pub mod kline;
utils.rs
pub fn get_size() -> (u32, u32) { ... }
chart/kline.rs
use utils; utils::get_size();
任何一個變量都是屬於一個做用域。做用域結束了,變量就刪除了。
這個做用域就擁有這個變量的全部權。
fn main() { { let x = 1; } println!("{}", x); // Error: x is dropped }
每一個數據類型賦值要麼move要麼copy。
copy type: i32, u32, f32, f64 ...
move type: String, Vec, HashMap
move類型之因此是move,由於複製成本過高。
move表示全部權的轉移。
fn main() { let n = 1; let n2 = n; println!("{} {}", n, n2); let v = vec![1, 2]; let v2 = v; println!("{}", v[0]); // Error: v is moved }
let a = &v1; // a的類型 &i32 let b = &mut v2; // b的類型 &mut i32
一個變量能夠擁有:
let mut v = 1_i32; let a = &mut v; let b = &mut v; // Error: cannot borrow `v` as mutable more than once at a time
如今咱們再試圖理解這段代碼:
impl Man { fn new(name: String, age: u8, weight: u8) -> Man { Man { name, age, weight } } fn eat(&mut self, food: String) { self.weight += 10; println!("{} eats a {}! Now weight: {}", self.name, food, self.weight); } fn sleep(&self) { println!("{} sleeps!", self.name); } }
&mut self
自動獲取實例的可變引用。&self
自動獲取實例的不可變引用。
vector大小可變,堆上分配。
array大小不可變。
slice是array或vector的一段引用。
let vector = vec![1, 2, 3, 4, 5]; let array = [2, 3]; let slice = &vector[1..3];
&str是對String的借用(引用),是個指向String的胖指針。
let s1 = "abc"; // &'static str let s2 = String::from("abc"); // String
被借用變量生命週期 > 借用者生命週期。
fn main() { let v; { let n = 10_i32; v = &n; // Error: `n` does not live long enough } }
編譯器沒法判斷變量的生命週期時,須要標記生命週期。
fn main() { let a = 100; let c; { let b = 4; c = choose(&a, &b); } println!("{}", c); } fn choose<'a, 'b>(a: &'a i32, b: &'b i32) -> &'a i32 { a }
trait相似於其餘編程語言中的接口。
fn calc<T: Into<f64>>(x: T) -> f64 { x.into() * 2. } calc(10_i32); calc(10_u32); calc(10_f32);
pub trait ToString { fn to_string(&self) -> String; } impl ToString for Man { fn to_string(&self) -> String { format!("Man {}", self.name) } } println!("{}", m);
甚至能夠給任意類型添加實現。
trait Barker { fn bark(&self); } impl<T> Barker for T { fn bark(&self) { println!("bark bark"); } } fn main() { 31.bark(); }
Orphan rule: 只要trait或類型有一個在當前包內,纔可添加trait實現。
struct Dog; struct Cat; trait Singer { fn sing(&self); } impl Singer for Dog { fn sing(&self) { println!("woof"); } } impl Singer for Cat { fn sing(&self) { println!("mew"); } } fn main() { let a: &Singer = &Dog; a.sing(); let a: &Singer = &Cat; a.sing(); }
堆上分配
let b = Box::new(1);
堆上分配+引用計數
struct Man { }
聲明一個不可變對象,其內部是可變的...
RefCell borrow(), borrow_mut()方法在運行時檢測借用規則,不然panic。
let c = RefCell::new(Man { name: "Bill".to_string(), age: 32 }); c.borrow_mut().age = 44;
RefCell主要用於引用類型。
Cell主要用於Copy類型。
#[derive(Debug)] struct Man { name: String }
佔位 {}
佔位Debug輸出 {:?}
佔位Debug輸出+beatify {:#?}
let m = Man{ name: String::from("Joe") }; println!("{greet}, {:?}", m, greet="Welcome");
let s = format!("{greet}, {:?}", m, greet="Welcome");
建立新項目
cargo new --bin demo-rust cargo new --lib demo-rust
Cargo.toml配置文件
[package] name = "demo-rust" version = "0.1.0" authors = ["Amadeus <gliheng@gmail.com>"] [dependencies] futures = "0.1.17" num = "0.1.40"
cargo run cargo build cargo test
使用外部包
extern crate serde;