变量 可变与不可变 1 2 let a = 10 ; let mut b = 20 ;
数据类型 整型
长度
有符号
无符号
8bits
i8
u8
16bits
i16
u16
32bits
i32
u32
64bits
i64
u64
128bits
i128
u128
与cpu架构相关
isize
usize
数字时指定类型,见下例中的9u32
1 println! ("9 / 2 = {} but 9.0 / 2.0 = {}" , 9u32 / 2 , 9.0 / 2.0 );
浮点型 类型为:f32
或f64
。浮点型默认为f64
。
1 2 let a: f32 = 10.0 ; let b = 11.0
布尔型 类型为:bool
;取值为:true
and false
字符与字符串 1 2 3 let c: char = 'f' ; let string_c: &str = "ace" ; let string_s = String ::from("hello" );
这里的string_c为“字符串切片”
元组 定义和访问元组
1 2 3 4 let x: (i32 , f64 , u8 ) = (500 , 6.4 , 1 );let five_hundred = x.0 ;let six_point_four = x.1 ;let one = x.2 ;
数组 1 2 3 4 5 let days = ["Sunday" , "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" ]; let bytes = [0 ; 5 ];let first = days[0 ];
数组的两个重要特征:数组的每个元素都具有相同的数据类型。 数据类型永远不会更改。数组大小是固定的。 长度永远不会更改。
向量 Vector 与数组不同之处在于,向量的大小或长度可以随时增大或缩小。 在编译时,大小随时间更改的功能是隐式的。 因此,Rust 无法像在数组中阻止越界访问一样在向量中阻止访问无效位置。
1 2 3 4 5 6 7 8 9 10 11 let three_nums = vec! [15 , 3 , 46 ]; println! ("Initial vector: {:?}" , three_nums);let mut fruit = Vec ::new();fruit.push("Apple" ); println! ("Pop off: {:?}" , fruit.pop());let mut index_vec = vec! [15 , 3 , 46 ]; let three = index_vec[1 ];
哈希表 1 2 3 4 5 6 7 8 9 10 use std::collections::HashMap; let mut reviews: HashMap<String , String > = HashMap::new();reviews.insert(String ::from("Ancient Roman History" ), String ::from("Very accurate." )); let book: &str = "Programming in Rust" ; println! ("\nReview for \'{}\': {:?}" , book, reviews.get(book));let obsolete: &str = "Ancient Roman History" ; reviews.remove(obsolete);
结构体 定义结构体 1 2 3 4 struct Student { name: String , level: u8 , remote: bool }struct Grades (char , char , char , char , f32 );
主要区别:经典结构中的每个字段都具有名称和数据类型。 元组结构中的字段没有名称。
实例化 1 2 3 4 5 6 7 8 let user_1 = Student { name: String ::from("Constance Sharma" ), remote: true , level: 2 };let mark_1 = Grades('A' , 'A' , 'B' , 'A' , 3.75 );println! ("{}, level {}. Remote: {}. Grades: {}, {}, {}, {}. Average: {}" , user_1.name, user_1.level, user_1.remote, mark_1.0 , mark_1.1 , mark_1.2 , mark_1.3 , mark_1.4 );
枚举 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 enum WebEvent { WELoad, WEKeys(String , char ), WEClick { x: i64 , y: i64 } } struct KeyPress (String , char );struct MouseClick { x: i64 , y: i64 }enum WebEvent { WELoad(bool ), WEClick(MouseClick), WEKeys(KeyPress) }let click = MouseClick { x: 100 , y: 250 };let keys = KeyPress(String ::from("Ctrl+" ), 'N' );let we_load = WebEvent::WELoad(true );let we_click = WebEvent::WEClick(click);let we_key = WebEvent::WEKeys(keys);
泛型 1 2 3 4 5 6 7 8 9 struct Container <T> { value: T, } impl <T> Container<T> { pub fn new (value: T) -> Self { Container { value } } }
函数 1 2 3 4 5 6 7 fn goodbye (message: &str ) { println! ("\n{}" , message); } fn divide_by_5 (num: u32 ) -> u32 { num / 5 }
所有权 所有权三原则
Each value in Rust has a variable that’s called its owner. (Rust中每一个变量都有一个所有者。)
There can only be one owner at a time.(在任一时刻,所有者有且仅有一个。)
When the owner goes out of scope, the value will be dropped.(当所有者离开其作用域后,它所拥有的数据会被释放。)
Copy Trait 凡是拥有Copy trait的数据类型,“=”都表示数据的复制而非传有权的转移。以下数据类型有Copy trait:
所有整型:u32 u64等
布尔型
所有浮点型:f32 f64等
字符型:char
元组(Tuples):如果组成元组的每个成员都有Copy trait,那么此元组也有Copy trait。
引用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 fn main () { let s1 = String ::from("hello" ); let len = calculate_length(&s1); println! ("The length of '{}' is {}." , s1, len); } fn calculate_length (s: &String ) -> usize { s.len() } fn main () { let mut s = String ::from("hello" ); change(&mut s); } fn change (some_string: &mut String ) { some_string.push_str(", world" ); }
引用的原则 引用的原则:
任何时刻,一个变量只能有
一个可变引用,或者
多个不可变引用
以上两点不可同时存在
引用应该总是合法的
Rust编译器在以下三个条件同时满足时,会产生数据竞争,发出编译错误:
两个或两个以上的pointer(包含所有者,可变引用)指向同一份数据。
其中至少一个可变引用指会向空间写入数据。
没有同步数据的访问机制。
手动批注生存期(lifetime annotation) 1 2 3 4 5 6 7 fn longest_word <'a >(x: &'a String , y: &'a String ) -> &'a String { if x.len() > y.len() { x } else { y } }
以上代码中,x和y的生命周期有可能不一样,所以函数返回值的生命周期实际上是由两个参数里生命周期较短的那个决定的。
条件判断 loop 在断点处返回一个值
1 2 3 4 5 6 7 8 9 let mut counter = 1 ;let stop_loop = loop { counter *= 2 ; if counter > 100 { break counter; } };
for 1 2 3 4 5 6 7 8 9 let big_birds = ["ostrich" , "peacock" , "stork" ];for bird in big_birds.iter() { println! ("The {} is a big bird." , bird); } for number in 0 ..5 { println! ("{}" , number * 2 ); }
while 1 2 3 4 while counter < 5 { println! ("We loop a while..." ); counter = counter + 1 ; }
Option与Result 枚举 原型 1 2 3 4 5 6 7 8 9 enum Option <T> { None , Some (T), } enum Result <T, E> { Ok (T): Err (E): }
Result 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #[derive(Debug)] struct DivisionByZeroError ;fn safe_division (dividend: f64 , divisor: f64 ) -> Result <f64 , DivisionByZeroError> { if divisor == 0.0 { Err (DivisionByZeroError) } else { Ok (dividend / divisor) } } fn read_file_contents (path: PathBuf) -> Result <String , Error> { let mut string = String ::new(); let mut file: File = match File::open(path) { Ok (file_handle) => file_handle, Err (io_error) => return Err (io_error), }; match file.read_to_string(&mut string) { Ok (_) => (), Err (io_error) => return Err (io_error), }; Ok (string) }
match 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 let fruits = vec! ["banana" , "apple" , "coconut" , "orange" , "strawberry" ];for &index in [0 , 2 , 99 ].iter() { match fruits.get(index) { Some (fruit_name) => println! ("It's a delicious {}!" , fruit_name), None => println! ("There is no fruit! :(" ), } } let a_number: Option <u8 > = Some (7 );match a_number { Some (7 ) => println! ("That's my lucky number!" ), _ => {}, } let a_number: Option <u8 > = Some (7 );if let Some (7 ) = a_number { println! ("That's my lucky number!" ); }
Trait Trait是一组类型可实现的通用接口。个人理解:类似于给类定义方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 trait Area { fn area (&self ) -> f64 ; } struct Circle { radius: f64 , } struct Rectangle { width: f64 , height: f64 , } impl Area for Circle { fn area (&self ) -> f64 { use std::f64 ::consts::PI; PI * self .radius.powf(2.0 ) } } impl Area for Rectangle { fn area (&self ) -> f64 { self .width * self .height } }
可以编写一个函数,该函数接受任何实现 AsJson Trait的类型
1 2 3 4 5 fn send_data_as_json (value: &impl AsJson) { println! ("Sending JSON data to server..." ); println! ("-> {}" , value.as_json()); println! ("Done!\n" ); }
迭代器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #[derive(Debug)] struct Counter { length: usize , count: usize , } impl Counter { fn new (length: usize ) -> Counter { Counter { count: 0 , length, } } } impl Iterator for Counter { type Item = usize ; fn next (&mut self ) -> Option <Self::Item> { self .count += 1 ; if self .count <= self .length { Some (self .count) } else { None } } }
宏 println 1 2 3 fn main () { println! ("The first letter of the English alphabet is {} and the last letter is {}." , 'A' , 'Z' ); }
derive(Debug) 通过#[derive(Debug)]
语法可以在代码执行期间查看某些在标准输出中无法查看的值。 要使用 println! 宏查看调试数据,请使用语法 {:#?} 以可读的方式格式化数据。
1 2 3 4 5 #[derive(Debug)] struct MouseClick { x: i64 , y: i64 }let m = MouseClick{ x: 20 , y: 30 };println! ("{:#?}" , m);
todo 1 todo!("Display the message by using the println!() macro" );
工具