前言
rust学习笔记,GitHub仓库:https://github.com/youngtaos/Rust-Learning.git。
一、创建Rust项目
1.cargo new
使用cargo new 可以简单创建一个rust项目
2.cargo.lock
此文件跟踪项目中依赖项的确切版本。
二、 编译和运行
1.cargo build
用 cargo build 构建了一个项目,并使用 ./target/debug/hello_cargo 运行它,
也可以使用 cargo run 来编译代码,然后运行生成的可执行文件
2.cargo run
使用 cargo run 比记住运行 cargo build 然后使用整个二进制路径更方便,因此大多数开发人员使用 cargo run。
3.cargo check
使用cargo check 比使用 cargo build 更快, 因为其会跳过生成可执行文件的步骤。
可以用来检查错误,确保项目可以编译成功。
4.cargo build --release
使用cargo build --release可以编译项目并对其进行优化
此命令将在 target/relese 而不是 target/debug 文件夹中创建可执行文件。
5.immutable
在Rust中,变量默认是不可变的
let immutable_variables = 1
6.mutable
也可以创建可变的变量
let mut mutable_variables = 2
三、关于输入输出
1.Input
IO
可以通过use std::io
引入io库,使用io::Stdin
获取用户的输入
也可以不用use std::io
引入io库,而是直接使用std::io::Stdin
,来获取用户的输入
Expect
read_line
将用户输入的任何内容放入我们传递给它的字符串中,但它也返回一个 Result 值。
这个Result 结果是一个枚举类型的值 Result<usize, Error>
如果 Result 的此实例是 Err 值,expect 将导致程序崩溃并显示您作为参数传递给expect 的消息。
如果 read_line 方法返回 Err,则可能是来自底层操作系统的错误的结果。
如果不调用expect
,将会收到警告:
warning: unused `Result` that must be used
--> src/main.rs:11:5
|
11 | / io::stdin()
12 | | .read_line(&mut guess);
| |______________________________^
|
= note: this `Result` may be an `Err` variant, which should be handled
= note: `#[warn(unused_must_use)]` on by default
help: use `let _ = ...` to ignore the resulting value
|
11 | let _ = io::stdin()
| +++++++
warning: `guessing_game` (bin "guessing_game") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.17s
2.&
& 表示该参数是一个引用,提供了一种让代码的多个部分访问一条数据的方法,而无需多次将该数据复制到内存中。
引用是一项复杂的功能,Rust 的主要优点之一是使用引用的安全性和易用性。 不需要知道很多细节来完成这个程序。 现在,您需要知道的是,与变量一样,默认情况下引用是不可变的。 因此,需要编写 &mut Guess 而不是 &Guess 来使其可变。
3.Println!
println!("You guessed: {guess}");
大括号 {} 组是一个占位符。
打印变量值时,变量名称可以放在大括号内。
let x = 5;
let y = 10;
println!("x = {x} and y + 2 = {}", y + 2);
打印表达式求值结果时,将空大括号放在格式字符串中,然后在格式字符串后跟上以逗号分隔的表达式列表,以相同的顺序在每个空大括号占位符中打印。 调用 println! 中打印变量和表达式的结果为x = 5 and y + 2 = 12
四、 scalar and compound
Rust 是一种静态类型语言, 这意味着它必须在编译时知道所有变量的类型
1.Scalar Types
Rust 有四种主要标量类型:整数、浮点数、布尔值和字符。
Integer Types
u32 类型。 此类型声明表明与其关联的值应该是占用 32 位空间的无符号整数(有符号整数类型以 i 而不是 u 开头)
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 |
每个变量可以是有符号的或无符号的,并且具有明确的大小。 有符号和无符号是指数字是否可能为负数,换句话说,数字是否需要带有符号(有符号),或者它是否只能为正数。
有符号数使用二进制补码表示形式存储。
-
有符号变量可以存储从 − ( 2 n − 1 ) -(2^n-1) −(2n−1) 到 ( 2 n / 2 ) − 1 (2^n/2)-1 (2n/2)−1(含)的数字,其中 n 是变体使用的位数。 因此,i8 可以存储从 − 2 7 -2^7 −27 到 2 7 − 1 2^7-1 27−1 的数字,相当于 -128 到 127。
-
无符号变量可以存储从 0 到 2 n − 1 2^n-1 2n−1 的数字,因此 u8 可以存储从 0 到 2 8 − 1 2^8-1 28−1 的数字,相当于 0 到 255。
此外, isize 和 usize 类型取决于程序运行所在计算机的体系结构,在表中表示为“arch”:如果使用 64 位体系结构,则为 64 位;如果使用 32 位体系结构,则为 32 位。
Floating-Point Types
Rust 还有两种浮点数的基本类型,即带小数点的数字。 Rust 的浮点类型是 f32 和 f64,其大小分别为 32 位和 64 位。
默认类型是 f64,因为在现代 CPU 上,它的速度与 f32 大致相同,但精度更高。
所有浮点类型都有符号。
fn main() {
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}
The Boolean Type
与大多数其他编程语言一样,Rust 中的布尔类型有两个可能的值:true 和 false。布尔值的大小为一字节。
fn main() {
let t = true;
let f: bool = false; // with explicit type annotation
}
The Character Type
fn main() {
let c = 'z';
let z: char = 'ℤ'; // with explicit type annotation
let heart_eyed_cat = '😻';
}
2.Compound Types
复合类型可以将多个值分组为一种类型。 Rust 有两种原始复合类型:元组和数组。
The Tuple Type
fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
}
元组是将具有多种类型的多个值组合在一起形成一个复合类型的通用方法。 元组有固定的长度:一旦声明,它们的大小就不能改变。
为了从元组中获取单个值,可以使用模式匹配来解构元组值:
fn main() {
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is: {y}");
}
我们还可以通过使用句点 (.) 后跟要访问的值的索引来直接访问元组元素:
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
拥有多个值的集合的另一种方法是使用数组。 与元组不同,数组的每个元素必须具有相同的类型。 与其他一些语言中的数组不同,Rust 中的数组具有固定长度。
Declare Array
Accessing Array Elements
Invalid Array Element Access
use std::io;
fn main() {
let a = [1, 2, 3, 4, 5];
println!("Please enter an array index.");
let mut index = String::new();
io::stdin()
.read_line(&mut index)
.expect("Failed to read line");
let index: usize = index
.trim()
.parse()
.expect("Index entered was not a number");
let element = a[index];
println!("The value of the element at index {index} is: {element}");
}
在以上代码中,访问了数组中不存在的元素。这将会导致 Rust 运行时错误。
程序因此退出并显示错误消息,不会执行最后的 println! 语句。
thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 10', src/main.rs:19:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Rust 的安全特性
- 当尝试使用索引访问元素时,Rust 将检查你指定的索引是否小于数组长度。
- 如果索引大于或等于数组长度,Rust 会出现 panic。
- 这种检查只能在运行时进行,比如在上面这种情况下,编译器无法在编译期知道用户运行代码时将输入什么值。