The Rust Programming Language
Rust
编程语言笔记。
来源:The Rust Programming Language Book 。
安装
使用 rustup
来安装 Rust
。
Rust
源文件以 .rs
作为扩展名。
几个常用的命令:
- 编译:
rustc .rs-file
- 运行:
./compiled-file
- 检查
Rust
编译器版本:rustc --version
- 检查
rustup
版本:rustup --version
- 更新
Rust
编译器:rustup update
- 卸载
Rust
和rustup
:rustup self uninstall
- 本地文档:
rustup doc
包管理工具
Rust 的包管理工具是 Cargo
。
几个常用的命令:
-
检查
cargo
的版本:cargo --version
-
新建项目:
cargo new
-
项目构建:
cargo build
-
运行项目:
cargo run
-
项目检查:
cargo check
:该命令确保项目可以编译,但不生成可执行文件,速度比cargo build
更快
包
Rust
使用 TOML(Tom's Obvious Minimal Language)
格式来管理依赖。
使用 cargo new
创建新项目后,在该项目的目录下会有名为 Cargo.toml
的文件来管理依赖和包。
可以使用 cargo add
来添加依赖,也可以在 .toml
文件的 [dependencies]
字段下添加包名。
例如:
[dependencies]
rand = "0.8.5"
包的版本使用三位的标准包标准。
在 .rs
文件中使用关键字 use
来导入包。
规范
Rust
的缩进采用的是 4 个space
,而不是tab
Rust
使用 snake case 对变量和函数命名,也就是全部使用小写字母,单词中间使用下划线_
连接,例如:var_name
Hello World
fn main() {
println!("Hello, World!");
}
fn
是函数(function)的关键词main()
是 Rust 的主函数、类似于 C、C++- 每行结束需要用分号
;
表示
注释
Rust
有三种注释:
- 单行注释:
//
- 多行注释:
/* */
- 文档(DocString)注释:
/** */
变量
Rust
是静态类型语言,在声明变量时需要使用关键词 let
并在冒号 :
后指明变量的类型。这点类似于 Python
的 Type-Hint 以及 TypeScript
。
let var: u8 = 0;
可修改性
Rust
中的所有变量都有可修改(mutable)或不可修改性(immutable),如果在声明变量时不明确指明,那么默认为不可修改。
使用关键字 mut
表示变量可以修改。
let mut var: u8 = 2;
u8 = 3; // That's OK
let ano_var: u8 = 2;
u8 = 3; // Error
shadowing
fn main() {
let x: u32 = 5;
let x = x + 1;
{
let x = x * 2;
println!("The inner x: {x}");
}
println!("The outer x: {x}");
}
// The inner x: 12
// The outer x: 6
如上述代码所示:声明了多个名为 x
的变量,在 Rust
中,我们称 第一个 x
被第二个 x
shadow,或者 第二个 x
overshadow 了第一个 x
,这意味着:当使用 x
这个变量时,编译器总是使用第二个 x
,即第二个 x
拿走了第一个 x
的所有,直到程序流离开第二个 x
的作用域或者第二个 x
也被 shadow。
shadow 和 mut 的区别
-
shadow 使得可以改变同名变量的类型,但是
mut
会在编译时出错fn main() { let x: &str = " "; let x: usize = x.len(); // 5 let mut x: &str = " "; x = x.len() // Error }
-
shadow 使得可以修改不可修改的同名变量的值
fn main() { let x: u32 = 5; x = 6; // Error, 因为没有变量默认是不可修改的 let x: u32 = 5; let x = 6; println!("{}", x) // 6 }
常量
Rust
使用 const
关键字声明常量。通常来说,需要用大写字母声明常量。
const THE_DAY_I_START_LEARNING_RUST: String = "2023.5.9";
不可修改的变量和常量的区别在于:
- 常量只能是不可修改的,不能通过
mut
关键字使得常亮可以修改 - 常量通常只赋值给常量声明的表达式,而不是运行时的计算表达式
- 常量可以在任何作用域(scope) 中声明,在程序运行期间,在其声明的作用域中是有效的
数据类型
Rust
是静态类型语言,因此在编译时就需要知道所有的变量类型。
例如在数据转换中:
fn main() {
let var = "100".parse().expect("Not a number!"); // Error
let var: u32 = "100".parse().expect("Not a number"); // OK, var == 100
}
基本类型
Rust
的基本数据类型有 4 种:
- 布尔 bool
- 整型 integer
- 浮点型 float
- 字符型 char
布尔型
布尔型有两个值:
- true
- false
整型
整型有 6 种长度,每种长度分类有符号和无符号两类。
长度 | 有符号 | 无符号 |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
整型字面量(literal)
字面量 | 举例 |
---|---|
十进制 | 98_222 |
十六进制 | 0xff |
八进制 | 0o77 |
二进制 | 0b1111_0000 |
字节(u8) | b'A' |
- 整型的默认类型为
i32
- 在使用集合类数据类型的索引时,使用
usize
或isize
浮点型
浮点型有两类,而且都是有符号的:
f32
f64
:默认类型
字符型
字符型用 c
(character)标识。
复合类型
Rust
的复合类型包括:
- 元组
- 数组
元组
元组 tuple
:用括号 ()
声明,元组元素的数据类型可以不同。
元组是定长的,一旦声明后就不能改变大小。
let tup: (u32, f32, bool) = (1, 2.2, true);
和 Python
不同,Rust
中的元组可以使用 .
运算符来访问。
let tup: (u32, f32, bool) = (1, 2.2, true);
println!("{}", tup.0); // 1
println!("{}", tup.2); // 2.2
println!("{}", tup.3); // true
数组
数组 array
: 用方括号 []
声明,数组元素的数据类型必须相同。
数组也是定长的。
let arr: [u8; 5] = [1, 2, 3, 4, 5];
;
的前后分别表示数组元素的类型和数组元素的个数。
可以使用索引 []
,访问数组元素,因为数组以定长形式存储在栈中:
let first = arr[0];
控制
条件
用 if, else if, else
等关键字控制程序流。
Rust
的条件语句不需要外嵌圆括号 ()
,但是也不同于 Python 的 :
,条件执行体需要用花括号:{}
。
fn main() {
let var: u32 = 8;
if var > 0 {
println!("{var} is greater than 0!");
} else if var < 0 {
println!("{var} is less than 0!");
} else {
println!("{var} is equal to 0!");
}
}
注:和 JavaScript
、Ruby
等语言不同,Rust
语言不会在条件判断时自动转换变量的类型,例如:
fn main() {
let var: bool = true;
if var == 0 {
println!("You can't get there in Rust");
}
}
循环
Rust
中有 3 种循环:
- 无限循环
loop
while
循环for
循环
结束、跳出循环的关键字:
break
跳出当前循环continue
结束本次循环(开始下一次循环)
loop 循环
Rust 可以使用关键字 loop
来创建无限循环,例如:
loop {
println!("This is a infinite loop");
}
// 等价于
while true {
println!("This is a infinite loop");
}
continue
对 loop
循环无效。
可以用 ``name给
loop` 循环命名(标识符)以跳出多层循环,例如:
fn main() {
let mut count: u32 = 10;
`outer: loop {
let mut remaining: u32 = 2;
loop {
println!("{}", count * remaining);
remaining -= 1;
if remaining == 0 {
break outer;
}
}
count -= 1;
println!("{}", count);
if count == 0 {
break;
}
}
}
while 循环
类似于其他语言的 while
循环。
同样,Rust
的循环条件语句不需要外嵌圆括号 ()
,但是也不同于 Python 的 :
,循环体需要用花括号:{}
。
fn main() {
let mut count = 10;
while count > 0 {
println!("{}", count);
count -= 1;
}
}
for 循环
for in
for in
循环对遍历对象中的每一个元素都执行遍历:
fn main() {
let arr: [u32; 5] = [1, 2, 3, 4, 5];
for element in arr {
println!("{}", element);
}
}
for range
for range
类似于 Python
的同名函数。
fn main() {
for i in 0..5 {
println!("{}", i);
}
}
使用 .rev()
倒序输出:
fn main() {
for i in (0..5).rev() {
println!("{}", i);
}
}
函数
使用关键字 fn
声明函数,Rust
总是首先执行 main
函数。
fn main() {
let var: u32 = 3;
increment_and_print(var);
}
fn increment_print(num: u32) -> u32 {
num += 1;
println!("{}", num);
return num;
// num
}
函数的参数需要声明名称和类型,返回值用 ->
表示,只需要声明类型。
可以使用关键字 return
显式返回值,也可以把返回值写在最后一行(不要使用 ;
结尾)。Rust
默认把最后一行的值作为返回值。
输入和输出
输入
使用标准库 std::io
来导入标准库的 io。
use std::io;
fn main() {
let mut inp: String = String::new();
io::stdin.read_line(&mut inp).expect("Failed to read");
println!("{inp}");
}
- 使用
stdin
引入标准输入流, - 使用
read_line(&)
来读取输入, - 使用
expect()
来处理异常情况。
输出
使用 println!()
来输出内容。
println!()
表示调用 macro,println()
表示调用函数
Rust
不支持直接输出变量的值,必须格式化(format)后输出。在引号 ""
中使花括号 {}
来输出变量。
fn main() {
let var: u32 = 15;
println!("{}", var); // 15
// println!("var equals {var}") Also ok!
// println!(var) Error!
}
结构体
Rust
的结构体类似于 C
,使用关键字 struct
声明。
结构体中的每个元素称为“域”(field),域是可修改的(mutable),使用 .
来访问域的值。
struct User {
active: bool,
sign_in_count: u32,
username: String,
email: String
}
fn main() {
let user = User {
active: false,
sign_in_count: 1,
username: String::from("someusername"),
email: String::from("someuseremail"),
};
user1.email = "anotheremail";
}
可以使用 ..
来简化域成员的赋值:
struct User {
active: bool,
sign_in_count: u32,
username: String,
email: String
}
fn main() {
let user = User {
active: false,
sign_in_count: 1,
username: String::from("someusername"),
email: String::from("someuseremail"),
};
let user_2 = User {
active: true,
..user1
}
}
上面的代码表示,除了域 active
之外,user_2
的其他域值和 user
相等。
注:..user
后没有 ,
。
枚举
例如下面的代码:
use std::cmp::Ordering;
use std:io;
fn main() {
println!("This is a guessing game");
const SECRET_NUMBER: u32 = 12;
let mut guess: String = String::new();
println!("Enter your guess: ");
io::stdin.read_line(&mut guess).expect("Failed to read line");
let mut guess = match guess.parse().wrap() {
Ok(num) => num,
Err(_) => {
println!("You should enter a number!");
}
}
match guess.cmp::Ordering {
Less => println!("Too small!"),
Greater => println!("Too big!"),
Equal => println!("You are the winner!");
}
}
match
关键字用于开始匹配枚举。
这段代码中用到了两个枚举类型,分别是:
- 对
guess
的类型判断会返回枚举类型Result
,它有Ok
和Err
两个枚举值,分别表示成功和错误两种情况, - 对
guess
和SECRET_NUMBER
两个值之间的比较会返回枚举类型Ordering
,它有Less
、Greater
和Equal
三种情况,分别表示小于,大于和等于。
待续
标签:笔记,var,let,fn,println,main,Rust From: https://www.cnblogs.com/risejl/p/17387723.html