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;