Cargo

Cargo New {project_name}: Creates a new project

Execute in the {project_name} directory:

Cargo Check: Calls the compiler for syntax checking, which is faster than build

Cargo Build: Builds the rust program

Cargo Run: Compiles and runs the program

Installing third-party Libraries

Add the third-party library name and version to cargo. Toml dependencies: rand = “0.7.0”

Running Cargo Build automatically downloads the third library for download and compilation

Cargo update (rand = “0.7.0”, cargo update (0.7.0, 0.8.0))

grammar

Declare variables:

Let: immutable variable, just like let in SWIFT, except that mutable variables need to be of the form let mut a = xx

// Rust shadow
fn main() {let a = 2;
let a = a + 1;
let a = a * 2;
println!("a = {}",a);  
}
// output: a = 6
// In other languages, there are usually errors with variables already declared
Copy the code

Error handling and enumeration:

Try {}catch{} try{}except{}..
// Rust uses pattern matching for processing (enumerations are handled the same way)
// 1. Error handling
let value = match enumValueExp {
   Ok(value) => value,
   Err( error ) => {
     	handle(error)
   }
}
// 2. Enumeration, here is the comparison of numbers, from the official tutorial guessing game
match guess.cmp(&secret_number) {
    Ordering::Less => println!("too small"),
    Ordering::Greater => println!("too big"),
    Ordering::Equal => {
        println!("win!"); }}Copy the code

Set type slice

let s = String::from("hello");
// The data structure of this pointer is PRT, len.
let slice = &s[0.2]; // PTR points to memory 0 of s, len = 2(2-0)
let slice = &s[..2];

let len = s.len();

let slice = &s[3..len];
let slice = &s[3. ] ;let slice = &s[0..len];
letslice = &s[..] ;Copy the code

Built-in types:

Unsigned integer:

U8: memory size 8bit [0, 2^ 8-1], U32, U64, U128, USize: based on the operating system instruction set (64-bit and 32-bit)

Signed integer:

I8: memory size 8bit Value range [-2^7, 2^ 7-1], i32, i64, i128, ISize: based on the current system (64-bit and 32-bit)

The interesting thing about Rust is that the official documentation mentions an integer overflow problem. A u8 variable, if 256 is typed, will have a value of 1. If 257 is typed, it will have a value of 2 and will not crash you. I want to write an example of a buffer overflow, but I’m not good enough to write it.

Floating point Numbers:

F32:32-bit single precision floating point number, F64:64-bit double precision floating point number

Boolean value types:

bool: true , false

Character types:

Char: 4 bytes (as opposed to char:1 in C, which uses ASCII as a single character, and rust, which uses unicode units of length).

Tuples:

fn main() {
	// subscript access
    let x: (i32.f64.u8) = (500.6.4.1);
    let five_hundred = x.0;
    let six_point_four = x.1;
    let one = x.2;
    // Assign access
    let (x, y, z) = x;
}
Copy the code

Array:

Features: Immutable length, memory distributed on the stack.

Use vector for variable lengths.

For example, if an array needs to hold the names of 12 months, the array should be used because it is always 12 and does not change.

let months = ["January"."February"."March"."April"."May"."June"."July"."August"."September"."October"."November"."December"];
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];
Copy the code

Function:

Fn funcName (arg1: type) -> type{}

Features: The last value expression, without the end; It can be used as a return value without return.

Tips:

The documentation also says, no; Is regarded as a value expression, and has; Is treated as a declarative expression.

The final expression in a Block ({}’) is the result of the settlement.

Personal thought: As long as it’s {}, you can try this.

Example:

/ / 1
fn main() {
    let x = 5;
    let y = {
        let x = 3;
        x + 1
    };
    println!("The value of y is: {}", y);
}
// y = 4

/ / 2
fn main() {
    let x = plus_one(5);
    println!("The value of x is: {}", x);
}
fn plus_one(x: i32) - >i32 {
    x + 1
}
// output x = 6
Copy the code

Control statements

if else

The basic syntax is similar to Swift, but with the SAO operation 😂

// The concept mentioned above comes..
fn main() {
    let condition = true;
    let number = if condition {5} else {6};
    println!("The value of number is: {}", number);
}
Copy the code

cycle

loop

Features: Can have a return value 🤔.

fn main() {
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2; }};println!("The result is {}", result);
}
// The result is 20
Copy the code

while

Bland, normal while

I also tried using break value inside;

Error 😂: can only break with a value inside loop or breakable block

for in

fn main() {
    let a = [10.20.30.40.50];
    for element in a.iter() {
        println!("the value is: {}", element);
    }
    for number in (1.4).rev() {
        println!("{}!", number);
    }
    println!("LIFTOFF!!!");
}
Copy the code

Memory management

Ownership

  1. Each value in Rust has a variable name called its owner. (for example: let name = “XXX”)
  2. There can only be one owner at a time.
  3. This value is removed when the owner goes out of scope.

—— Ownership from Rust

// This value is removed when the owner is out of scope.
{
 // On the stack, because at compile time, the value is already determined
	let str1 = "123";
  // Put it on the heap
	let str2 = String::from("1233");
}
/ / str1 stack
// The str2 pointer to the heap has been freed
Copy the code

Heap variable

When assigning values, a shallow copy is used (just the memory of the copied pointer), but the difference is that the previous pointer is free; rust calls it move

There can be only one owner at a time
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1); // The compiler will report an error
Copy the code

To make a deep copy, call.clone()

let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
Copy the code

Stack variable

When assigning, copying is done by default

let x = 5;
let y = x;
println!("x = {}, y = {}", x, y);
Copy the code

Those that follow the Copy trait will automatically Copy when assigned, just as common scalar types do, but those that already follow the Drop trait will not follow the Copy trait.

Quote and borrow

By using references in Rust, Ownership is not created, and therefore memory is not released when the pointer is released.

I think it’s better to think of it as borrowing, as mentioned in the document, you need something, others have it, you can borrow it, but you don’t own it, you can’t dispose of it, because after using it, you have to return it to others.

Immutable reference

fn main() {let s1 = String::from("hello");
	let len = calculate_length(&s1);
}
fn calculate_length(s: &String) - >usize { // s is a reference to a String
    s.len()
}
Copy the code

The variable reference

fn main() {
    let mut s = String::from("hello");
    change(&mut s);
}
fn change(some_string: &mut String) {
    some_string.push_str(", world");
}
Copy the code

limit

  1. Only one mutable reference can be declared for the same variable in the same scope, not multiple mutable references.

    This is done to avoid unknown errors in the event of data contention, the document states. (Multiple reads, multiple reads at the same time, and no synchronization mechanism)

    let mut s = String::from("hello");
    
    let r1 = &mut s;
    let r2 = &mut s;
    
    println!("{}, {}", r1, r2);
    Copy the code

    The error is as follows:

    error[E0499]: cannot borrow `s` as mutable more than once at a time
     --> src/main.rs:5:14
      |
    4 |     let r1 = &mut s;
      |              ------ first mutable borrow occurs here
    5 |     letr2 = &mut s; | ^^^^^^ second mutable borrow occurs here 6 | 7 | println! ("{}, {}", r1, r2);
      |                        -- first borrow later used here
    Copy the code
  2. In the same scope, an immutable reference is declared. A mutable reference cannot be declared if the pointer has not been reclaimed.

    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);
    Copy the code

    The error is as follows:

    error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
     --> src/main.rs:6:14
      |
    4 |     let r1 = &s; // no problem
      |              -- immutable borrow occurs here
    5 |     let r2 = &s; // no problem
    6 |     letr3 = &mut s; // BIG PROBLEM | ^^^^^^ mutable borrow occurs here 7 | 8 | println! ("{}, {}, and {}", r1, r2, r3);
      |                                -- immutable borrow later used here
    Copy the code
  3. Hanging pointer (wild pointer)

The examples cited here relate primarily to rust’s life cycle

fn main() {
  let reference_to_nothing = dangle();
}
fn dangle() - > &String {
      let s = String::from("hello");

      &s // Since there is a reference, all useless Ownership will be reclaimed when out of scope.
}
Copy the code

The error is as follows:

error[E0106]: missing lifetime specifier
   --> main.rs:5:16
  |
  5 | fn dangle() -> &String {
    |                ^ expected lifetime parameter
    |
    = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from = help: consider giving it a 'static lifetime
Copy the code

Solutions:

Direct return variable

fn no_dangle() - >String {
    let s = String::from("hello");

    s
}
Copy the code

Struct

The statement

We are only talking about cases where the field type is not a reference. The ownership is all in the struct.

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,}// Tuple structure
struct Color {u32.u32.u32.u32}
Copy the code

Initialize the

  1. The first kind of
let user1 = User {
    email: String::from("[email protected]"),
    username: String::from("someusername123"),
    active: true,
    sign_in_count: 1};let color = Color(255.255.255.255)
Copy the code
  1. The second is when the variable name and parameter name are exactly the same
fn build_user(email: String, username: String) -> User {
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,}}Copy the code
  1. The third, updated from another instance, is syntactic sugar.

Use.. Specify the instance so that the values of the remaining fields are the same as the instance.

In this case, user2 has the same values as user1 except for the email and usENAME fields.

let user2 = User {
    email: String::from("[email protected]"),
    username: String::from("anotherusername567"),
    ..user1
};
Copy the code

Print stUCT information

  1. **println! Replace {} in ** with {:? } or {: #? }(Optimize print information format)

  2. Enable STUCt to implement STD :: FMT ::Debug using #[derive(Debug)]

#[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 }
Copy the code

Define methods

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,}impl Rectangle {
    fn area(&self) - >u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}
Copy the code

Using &self: read-only does not change the contents of the struct.

Case of &mut self: read and write, can update the contents of stuct.

Using self: The method takes ownership of self, and when it leaves the method’s scope, self is released. This is usually used in specific conversion situations, such as when you convert binary data to JSON data and will not use binary data later.

Tips:

Rect1.area () is equivalent to (&rect1).area() or (&mut rect1).area() if &mut self. This is written because Rust automatically adds &, &mut, or *.

In C++ :(*object).func() is equivalent to object->func().

There is no -> operator in Rust.

Defining the correlation function

Similar to what we call class methods

impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Rectangle { width: size, height: size }
    }
}
let square = Rectangle::square(20);
Copy the code

To be continued…..