文章目录
- Variables and Mutability
- Shadowing
- Data Types
- Scalar Types
- Compound Types
- Functions
- Function Parameters
- Comments
- Control Flow
- Repetition with Loops
Variables and Mutability
rust">fn main() {
let mut x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
rust">fn main() {
let x = 5;
let x = x + 1;
let x = x * 2;
println!("The value of x is: {}", x);
}
- constant:
const MAX_POINTS: u32 = 100_000;
Shadowing
The other difference between mut
and shadowing is that because we’re effectively creating a new variable when we use the let
keyword again, we can change the type of the value but reuse the same name.
Data Types
Keep in mind that Rust is a statically typed language, which means that it must know the types of all variables at compile time.
Scalar Types
-
Integer Types
- Signed numbers are stored using two’s complement representation.
- Each signed variant can store numbers from
−
(
2
n
−
1
)
-(2^{n - 1})
−(2n−1) to
2
n
−
1
−
1
2^{n - 1} - 1
2n−1−1 inclusive, where n is the number of bits that variant uses. So an
i8
can store numbers from − ( 2 7 ) -(2^7) −(27) to 2 7 − 1 2^7 - 1 27−1, which equals -128 to 127. Unsigned variants can store numbers from 0 to 2 n − 1 2^n - 1 2n−1, so au8
can store numbers from 0 to 2 8 − 1 2^8 - 1 28−1, which equals 0 to 255. - The
isize
andusize
types depend on the kind of computer your program is running on: 64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit architecture. - All number literals except the byte literal allow a type suffix, such as
57u8
, and_
as a visual separator, such as1_000
. - Integer Overflow
-
Floating-Point Types
rust">fn main() { let x = 2.0; // f64 let y: f32 = 3.0; // f32 }
-
The Boolean Type
-
The Character Type
- 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.
- Rust’s
Compound Types
-
The Tuple Type
-
Tuples have a fixed length: once declared, they cannot grow or shrink in size.
rust">fn main() { let tup: (i32, f64, u8) = (500, 6.4, 1); }
-
destructure by pattern matching:
rust">fn main() { let tup = (500, 6.4, 1); let (x, y, z) = tup; println!("The value of y is: {}", y); }
-
period(
.
):rust">fn main() { 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 (fixed length)
rust">fn main() { let a = [1, 2, 3, 4, 5]; }
rust">let a: [i32; 5] = [1, 2, 3, 4, 5];
rust">let a = [3; 5];
rust">let a = [3, 3, 3, 3, 3];
- An array is a single chunk of memory allocated on the stack.
- Invalid Array Element Access
Functions
You’ve also seen the fn
keyword, which allows you to declare new functions.
Rust code uses snake case as the conventional style for function and variable names.
rust">fn main() {
println!("Hello, world!");
another_function();
}
fn another_function() {
println!("Another function.");
}
Rust doesn’t care where you define your functions, only that they’re defined somewhere.
Function Parameters
- 形参 parameter
- 实参 argument
rust">fn main() {
another_function(5, 6);
}
fn another_function(x: i32, y: i32) {
println!("The value of x is: {}", x);
println!("The value of y is: {}", y);
}
- Statements are instructions that perform some action and do not return a value.
- Expressions evaluate to a resulting value.
- Statements do not return values. Therefore, you can’t assign a
let
statement to another variable.
rust">fn main() {
let x = 5;
let y = {
let x = 3;
x + 1
};
println!("The value of y is: {}", y);
}
This expression:
rust">{
let x = 3;
x + 1
}
is a block that, in this case, evaluates to 4
. That value gets bound to y
as part of the let statement. Note the x + 1
line without a semicolon at the end, which is unlike most of the lines you’ve seen so far. Expressions do not include ending semicolons. If you add a semicolon to the end of an expression, you turn it into a statement, which will then not return a value.
In Rust, the return value of the function is synonymous with the value of the final expression in the block of the body of a function. You can return early from a function by using the return
keyword and specifying a value, but most functions return the last expression implicitly.
rust">fn five() -> i32 {
5
}
fn main() {
let x = five();
println!("The value of x is: {}", x);
}
rust">fn main() {
let x = plus_one(5);
println!("The value of x is: {}", x);
}
fn plus_one(x: i32) -> i32 {
x + 1
}
Comments
Control Flow
rust">fn main() {
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}
It’s also worth noting that the condition in this code must be a bool
.
Rust will not automatically try to convert non-Boolean types to a Boolean. You must be explicit and always provide if
with a Boolean as its condition.
rust">fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {}", number);
}
In this case, the value of the whole if
expression depends on which block of code executes. This means the values that have the potential to be results from each arm of the if
must be the same type.
Repetition with Loops
-
loop
Theloop
keyword tells Rust to execute a block of code over and over again forever or until you explicitly tell it to stop.rust">fn main() { let mut counter = 0; let result = loop { counter += 1; if counter == 10 { break counter * 2; } }; println!("The result is {}", result); }
-
while
rust"> fn main() { let mut number = 3; while number != 0 { println!("{}!", number); number -= 1; } println!("LIFTOFF!!!"); }
-
for
rust">fn main() { let a = [10, 20, 30, 40, 50]; for element in a.iter() { println!("the value is: {}", element); } }
rust">fn main() { for number in (1..4).rev() { println!("{}!", number); } println!("LIFTOFF!!!"); }