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
- Each value in Rust has a variable name called its owner. (for example: let name = “XXX”)
- There can only be one owner at a time.
- 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
-
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
-
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
-
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
- 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
- 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
- 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
-
**println! Replace {} in ** with {:? } or {: #? }(Optimize print information format)
-
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…..