# Learn Rust

## Install

https://www.rust-lang.org/tools/install

## Common Programming Concepts

### Variables And Mutability

  1 2 3 4 5 6 7 8 9 10  fn main() { let x = 5; x = 6; // error x是不可变的 const MAX_POINTS: u32 = 100_000; // 常量， 和不可变的变量不同，常量只能由常量表达式初始化 // 数字里的下划线只是提高可读性 let mut x = 5; // 同时 shadow 上面的 x, 这是一个新的变量，类型也可以不同 x = 6; // 正确 } 

### 数据类型 Data Type

Rust has four primary scalar types: integers, floating-point numbers, Booleans, and characters

#### Integer Types

Integer Types in Rust:

Length Signed Unsigned
8-bit i8 u8
16-bit i16 u16
32-bit i32 u32
64-bit i64 u64
128-bit i128 u128
arch isize usize

Integer Literals in Rust:

Number literals Example
Decimal 98_222
Hex 0xff
Octal 0o77
Binary 0b1111_0000
Byte (u8 only) b'A'

#### Floating-Point Types

Rust’s floating-point types are f32 and f64, which are 32 bits and 64 bits in size, respectively.

IEEE-754 standard:

#### The Boolean Type

 1 2 3 4 5  fn main() { let t = true; let f: bool = false; // with explicit type annotation } 

#### Character Type

 1 2 3 4 5  fn main() { let c = 'z'; let z = 'ℤ'; let heart_eyed_cat = '😻'; } 

Rust’s char type is four bytes in size and represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII.

#### Compound Types

The Tuple Type

Tuples have a fixed length: once declared, they cannot grow or shrink in size.

  1 2 3 4 5 6 7 8 9 10 11  fn main() { let tup: (i32, f64, u8) = (500, 6.4, 1); let tup2 = (500, 6.4, 1); let (x, y, z) = tup2; let x: (i32, f64, u8) = (500, 6.4, 1); let five_hundred = x.0; let six_point_four = x.1; let one = x.2; } 

The Array Type

arrays in Rust have a fixed length

  1 2 3 4 5 6 7 8 9 10  fn main() { let a = [1, 2, 3, 4, 5]; let a: [i32; 5] = [1, 2, 3, 4, 5]; // 指定类型和数量 let a = [3; 5]; // 等同于 let a = [3, 3, 3, 3, 3]; let first = a[0]; let second = a[1]; } 

### 函数 Function

 1 2 3 4 5 6 7 8 9  fn main() { println!("Hello, world!"); another_function(); } fn another_function() { println!("Another function."); } 

#### Function Parameters

 1 2 3 4 5 6 7  fn main() { another_function(5); } fn another_function(x: i32) { println!("The value of x is: {}", x); } 

#### Statement & Expression

 1 2 3 4 5 6 7 8 9  let x = 6; // 语句 let y = (let x); // 错误 let x = 5+6; // 5+6是表达式 ,表达式可以是声明的一部分 let y = { // 使用 {} 括起来的块也是表达式， 最后一条不已分号结尾的是表达式返回值 let x = 3; x + 1 }; // 

#### Return Value

 1 2 3 4 5 6 7  fn five() -> i32 { // 最后一条不加分号的表达式，当作返回值 5 } fn five() -> i32 { // 也可以显示调用return，在任意位置返回 return 5; } 

### 注释 Comments

 1  // comment 

### 控制流 Control Flow

#### 分支

  1 2 3 4 5 6 7 8 9 10 11  if number % 4 == 0 { println!("number is divisible by 4"); } else if number % 3 == 0 { println!("number is divisible by 3"); } else if number % 2 == 0 { println!("number is divisible by 2"); } else { println!("number is not divisible by 4, 3, or 2"); } let number = if condition { 5 } else { 6 }; // 不以分号结尾的，当作表达式返回值 

#### 循环

  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 40 41 42  fn main() { loop { println!("again!"); } } // 带返回值的 loop fn main() { let mut counter = 0; let result = loop { counter += 1; if counter == 10 { break counter * 2; } }; println!("The result is {}", result); // 20 } // 条件循环 while number != 0 { println!("{}!", number); number -= 1; } // for 循环 fn main() { let a = [10, 20, 30, 40, 50]; for element in a.iter() { println!("the value is: {}", element); } } fn main() { for number in (1..4).rev() { println!("{}!", number); // 3! 2! 1! } println!("LIFTOFF!!!"); } 

### 所有权 Ownership

rust中最重要的也是独有的概念，内存是通过带有一组规则的所有权系统管理的，编译器在编译时检查这些规则，不会影响程序的执行效率

#### 规则

• 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.
• 当所有者超出作用域，该值会被删除

#### String type

string literal 字符串字面值， 被硬编码在代码中，不能更改

 1  let s = "hello"; 

String，这种类型分配在堆上，因此能够存储编译时未知的大量文本。可以通过字符串字面值来创建

 1 2  let s = String::from("hello"); // :: namespace let mut s = String::from("hello"); 

GC语言自动管理内存，C++有allocfree，而rust,一旦拥有内存的变量超出范围，就会自动归还内存。

 1 2 3 4  { let s = String::from("hello"); // s is valid } // s 被释放 

When a variable goes out of scope, Rust calls a special function for us. This function is called drop, and it’s where the author of String can put the code to return the memory. Rust calls drop automatically at the closing curly bracket.

#### 变量与数据交互的方式：移动

 1 2  let s1 = String::from("hello"); let s2 = s1; 

rust如果用浅拷贝，那么前面说了会自动调用drop，存在双重释放的问题

Rust认为s1不再有效，因此，当s1超出作用域时，它不需要释放任何内存。

 1 2 3 4  let s1 = String::from("hello"); let s2 = s1; println!("{}, world!", s1); // error 

we would say that s1 was moved into s2.

Rust永远不会自动创建数据的深层副本。因此，就运行时性能而言，可以认为任何自动复制都是廉价的。

#### 克隆

 1 2 3 4  let s1 = String::from("hello"); let s2 = s1.clone(); println!("s1 = {}, s2 = {}", s1, s2); // ok 

#### 拷贝

 1 2  let x = 5; let y = x; // 这是拷贝，内置类型，大小固定，栈上分配，传拷贝 

Rust has a special annotation called the Copy trait ， 可以指示编译器将类型放在栈上，像一个整数类型一样

• All the integer types, such as u32.
• The Boolean type, bool, with values true and false.
• All the floating point types, such as f64.
• The character type, char.
• Tuples, if they only contain types that are also Copy. For example, (i32, i32) is Copy, but (i32, String) is not.
• 数组也是，内部元素必须是 copy 类型

#### 所有权与函数

 1 2 3 4 5 6 7  let s = String::from("hello"); takes_ownership(s); // s 这里无效了 let x = 5; makes_copy(x); // x 仍然有效 

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  fn main() { let s1 = gives_ownership(); let s2 = String::from("hello"); let s3 = takes_and_gives_back(s2); // s2 无效了 } fn gives_ownership() -> String { let some_string = String::from("hello"); some_string } fn takes_and_gives_back(a_string: String) -> String { a_string } 

#### 引用和借用 References and Borrowing

  1 2 3 4 5 6 7 8 9 10 11 12  fn main() { let s1 = String::from("hello"); let (s2, len) = calculate_length(s1); println!("The length of '{}' is {}.", s2, len); } fn calculate_length(s: String) -> (String, usize) { let length = s.len(); // len() returns the length of a String (s, length) } 

  1 2 3 4 5 6 7 8 9 10 11 12  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() }// Here, s goes out of scope. But because it does not have ownership of what // it refers to, nothing happens. 

&s1创建了一个指向s1的引用，但是并不拥有它，所以引用离开作用域时，不会影响s1

Because it does not own it, the value it points to will not be dropped when the reference goes out of scope.

 1 2 3  fn change(some_string: &String) { some_string.push_str(", world"); // error } 

Just as variables are immutable by default, so are references. We’re not allowed to modify something we have a reference to.

 1 2 3 4 5 6 7 8 9  fn main() { let mut s = String::from("hello"); change(&mut s); } fn change(some_string: &mut String) { // &mut 可变引用 some_string.push_str(", world"); } 

 1 2 3 4 5 6  let mut s = String::from("hello"); let r1 = &mut s; let r2 = &mut s; // error println!("{}, {}", r1, r2); 

 1 2 3 4 5 6 7  let mut s = String::from("hello"); { let r1 = &mut s; } // r1 goes out of scope here, so we can make a new reference with no problems. let r2 = &mut s; 

 1 2 3 4 5 6 7  let mut s = String::from("hello"); let r1 = &s; // no problem let r2 = &s; // no problem let r3 = &mut s; // BIG PROBLEM println!("{}, {}, and {}", r1, r2, r3); 

 1 2 3 4 5 6 7 8 9  let mut s = String::from("hello"); let r1 = &s; // no problem let r2 = &s; // no problem println!("{} and {}", r1, r2); // r1 and r2 are no longer used after this point let r3 = &mut s; // no problem println!("{}", r3); 

  1 2 3 4 5 6 7 8 9 10  fn main() { let reference_to_nothing = dangle(); } fn dangle() -> &String { let s = String::from("hello"); &s } // 这里返回了引用，然后s销毁了，所以引用悬空了，编译器不会让这样的情况发生 // 这里应该直接返回字符串 

• At any given time, you can have either one mutable reference or any number of immutable references.
• References must always be valid.

#### 切片 slices

a different kind of reference: slices.

  1 2 3 4 5 6 7 8 9 10 11  fn first_word(s: &String) -> usize { let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return i; } } s.len() } 

Because the enumerate method returns a tuple, we can use patterns to destructure that tuple, just like everywhere else in Rust.

Because we get a reference to the element from .iter().enumerate(), we use & in the pattern.

  1 2 3 4 5 6 7 8 9 10 11  let s = String::from("hello world"); let hello = &s[0..5]; let world = &s[6..11]; // let slice = &s[0..2]; // let slice = &s[..2]; 等效 // let slice = &s[3..len]; // let slice = &s[3..]; 等效 // let slice = &s[0..len]; // let slice = &s[..]; 等效 

  1 2 3 4 5 6 7 8 9 10 11  fn first_word(s: &String) -> &str { let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[0..i]; } } &s[..] } 

 1 2 3 4 5 6 7 8 9  fn main() { let mut s = String::from("hello world"); let word = first_word(&s); s.clear(); // error! println!("the first word is: {}", word); } 

if we have an immutable reference to something, we cannot also take a mutable reference. Because clear needs to truncate the String, it needs to get a mutable reference. Rust disallows this, and compilation fails.

 1  let s = "Hello, world!"; 

The type of s here is &str: it’s a slice pointing to that specific point of the binary. This is also why string literals are immutable; &str is an immutable reference.

 1 2 3 4  fn first_word(s: &String) -> &str { } fn first_word(s: &str) -> &str { } 

  1 2 3 4 5 6 7 8 9 10 11  fn main() { let my_string = String::from("hello world"); let word = first_word(&my_string[..]); let my_string_literal = "hello world"; // 可以在一个切片上，继续创建切片 let word = first_word(&my_string_literal[..]); let word = first_word(my_string_literal); } 
##### 其他切片

 1 2 3  let a = [1, 2, 3, 4, 5]; let slice = &a[1..3]; // &[i32] 

You’ll use this kind of slice for all sorts of other collections.

### 结构体 Structs

#### 声明与创建

 1 2 3 4 5 6  struct User { username: String, email: String, sign_in_count: u64, active: bool, } 

 1 2 3 4 5 6 7  let mut user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; user1.email = String::from("anotheremail@example.com"); 

 1 2 3 4 5 6 7 8  fn build_user(email: String, username: String) -> User { User { email, username, active: true, sign_in_count: 1, } } 

 1 2 3 4 5  let user2 = User { email: String::from("another@example.com"), username: String::from("anotherusername567"), ..user1 }; 

 1 2 3 4 5  struct Color(i32, i32, i32); struct Point(i32, i32, i32); // 他们时不同类型 let black = Color(0, 0, 0); let origin = Point(0, 0, 0); 

#### Derived Traits

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!("rect1 is {}", rect1); // err Rectangle doesn't implement std::fmt::Display // help the trait std::fmt::Display is not implemented for Rectangle // note: in format strings you may be able to use {:?} (or {:#?} for pretty-print) instead } 

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19  #[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!("rect1 is {:?}", rect1); // rect1 is Rectangle { width: 30, height: 50 } // 如果使用 {:#?} //rect1 is Rectangle { // width: 30, // height: 50, //} } 

Rust has provided a number of traits for us to use with the derive annotation that can add useful behavior to our custom types.

#### 方法

  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  #[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { // 不可变借用自己 self.width * self.height } fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!( "The area of the rectangle is {} square pixels.", rect1.area() ); } 

To define the function within the context of Rectangle, we start an impl (implementation) block.

rust没有c++中的->操作符，解除引用时自动完成的

Rust has a feature called automatic referencing and dereferencing.

Here’s how it works: when you call a method with object.something(), Rust automatically adds in &, &mut, or * so object matches the signature of the method. In other words, the following are the same:

 1 2  p1.distance(&p2); // 等效 (&p1).distance(&p2); 

Associated Functions 关联函数，类似c++的静态成员函数

  1 2 3 4 5 6 7 8 9 10 11  impl Rectangle { fn square(size: u32) -> Rectangle { Rectangle { width: size, height: size, } } } // 调用时使用 :: let sq = Rectangle::square(3); 

the :: syntax is used for both associated functions and namespaces created by modules.

::用在关联函数和命名空间

  1 2 3 4 5 6 7 8 9 10 11  impl Rectangle { fn area(&self) -> u32 { self.width * self.height } } impl Rectangle { fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } }