2023-09-18 23:11:06 +08:00

259 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Rust
date: 2023-09-15 09:25:54
tags:
---
# Rust 教程
## 第一个 Rust 程序
Rust语言代码文件后缀名为`.rs`如helloworld.rs。
```rust
fn main() {
println!("Hello World!");
}
```
使用`rustc`命令编译helloworld.rs文件
```shell
rustc helloworld.rs # 编译 helloworld.rs 文件
```
编译后会生成helloworld可执行文件
```shell
./helloworld # 执行 helloworld
Hello World!
```
# Rust 环境搭建
## 安装 Rust 编译工具
Rust 编译工具从链接 [安装 Rust - Rust 程序设计语言 (rust-lang.org)](https://www.rust-lang.org/zh-CN/tools/install) 中下载的Rustup安装。下载好的Rustup在Windows 上是一个可执行程序 rustup-init.exe。在其他平台上应该是`rustup-init.sh`)。
现在执行 rustup-init 文件:
![image-20230915102448742](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20230915102448742.png)
![image-20230915135358199](https://markdownhexo.oss-cn-hangzhou.aliyuncs.com/img/image-20230915135358199.png)
上图显示的是一个命令行安装向导。
**如果你已经安装MSVC推荐那么安装过程会非常的简单输入 1 并回车,直接进入第二步。**
如果你安装的是MinGW那么你需要输入 2自定义安装然后系统会询问你 Default host triple?,请将上图中 **default host triple**的"msvc"改为"gnu"再输入安装程序:
![img](https://www.runoob.com/wp-content/uploads/2020/04/rust-env2.png)
其他属性都默认。
设置完所有选项,会回到安装向导界面(第一张图),这时我们输入 1 并回车即可。
![img](https://www.runoob.com/wp-content/uploads/2020/04/rust-env3.png)
进行到这一步就完成了Rust的安装可以通过以下命令测试
```shell
rustc -V # 注意大写的 V
```
![img](https://www.runoob.com/wp-content/uploads/2020/04/rust-env4.png)
如果以上两个命令能够输出你安装的版本号,就是安装成功了。
## 搭建 Visual Studio Code 开发环境
安装`rust-analyzer``Native Debug`两个扩展。
![img](https://www.runoob.com/wp-content/uploads/2020/04/49033261-B1B8-4D70-8090-53DC45A8727E.jpeg)
![img](https://www.runoob.com/wp-content/uploads/2020/04/rust-env8.png)
重新启动 VsCodeRust 的开发环境就搭建好了。
现在新建一个文件夹,如 RustLearn。
在VsCode中打开新建的文件夹。
打开文件夹后,新建终端。
输入以下命令:
```shell
cargo new greeting
```
当前文件夹下会构建一个名叫 greeting 的 Rust 的工程目录。
在终端里输入以下三个命令:
```shell
cd ./greeting
cargo build
cargo run
```
系统在创建工程时会生成一个Hello World源程序main.rs这时会被编译运行
# Cargo 教程
## Cargo 是什么
Cargo 是 Rust 的构建系统和包管理器。
Rust 开发者 常用 Cargo 来管理 Rust 工程和获取工程所依赖的库。在上个教程中我们曾使用 cargo new greeting 命令创建一个名为 greeting 的工程Cargo 新建了一个名为 greeting 的文件夹并在里面部署了一个 Rust 工程最典型的文件结构。这个 greeting 文件夹就是工程本身。
## Cargo 功能
Cargo 除了创建工程以外还具备构建build工程、运行run工程等一系列功能构建和运行分别对应以下命令
```shell
cargo build
cargo run
```
Cargo 还具有获取包、打包、高级构建等功能,详细使用方法参见 Cargo 命令。
```shell
cargo clippy # 类似ESLintlint工具检查代码可以优化的地方
cargo fmt # 类似go fmt代码格式化
cargo tree # 查看第三方库的版本和依赖关系
cargo bench # 运行benchmark基准测试性能测试
cargo udeps # (第三方)检查项目中未使用的依赖
# 另外cargo build/run --release 使用release编译会比默认的debug编译性能提升10倍以上但是 release 缺点是编译速度较慢,而且不会显示 panic backtrace 的具体行号
```
## 在 VsCode 中配置 Rust 工程
Cargo 是一个不错的构建工具如果使VsCode 与它相配合那么 VsCode 将会是一个十分便捷的开发环境。
在上一章中我们建立了 greeting 工程,现在我们用 VsCode 打开 greeting 文件夹**(注意不是 RustLeanrning**。
打开 greeting 之后,在里面新建一个新的文件夹`.vscode`
# Rust 输出到命令行
在正式学习 Rust 语言以前,我们需要先学会怎样输出一段文字到命令行,这几乎是学习每一门语言之前必备的技能,因为输出到命令行几乎是语言学习阶段程序表达结果的唯一方式。
在之前的 Hello, World 程序中大概已经告诉了大家输出字符串的方式,但并不全面,大家可能很疑惑为什么 println!( "Hello World") 中的 println 后面还有一个 `!` 符号,难道 Rust 函数之后都要加一个感叹号显然并不是这样。println 不是一个函数,而是一个宏规则。这里不需要更深刻的挖掘宏规则是什么,后面的章节中会专门介绍,并不影响接下来的一段学习。
Rust 输出文字的方式主要有两种:`println!()``print!()`。这两个"函数"都是向命令行输出字符串的方法,区别仅在于前者会在输出的最后附加输出一个换行符。当用这两个"函数"输出信息的时候,第一个参数是格式字符串,后面是一串可变参数,对应着格式字符串中的"占位符",这一点与 C 语言中的 printf 函数很相似。但是Rust 中格式字符串中的占位符不是 **"% + 字母"** 的形式,而是一对 **{}**。
`printlna.rs`文件
```rust
fn main() {
let a = 12;
println!("a is {}", a);
}
```
使用`rustc`命令编译`printlna.rs`文件:
```rust
rustc printlna.rs # 编译 printlna.rs 文件
```
编译后会生成 `printlna`可执行文件:
```shell
./printlna # 执行 printlna
```
以上程序的输出结果是:
```shell
a is 12
```
如果我想把 a 输出两遍,那岂不是要写成:
```rust
println!("a is {}, a again is {}", a, a);
```
其实有更好的写法:
```rust
println!("a is {0}, a again is {0}", a);
```
`{}`之间可以放一个数字它将把之后的可变参数当做一个数组来访问下标从0开始。
如果要输出 **{** 或 **}** 怎么办呢?格式字符串通过 **{{** 和 **}}** 分别转义代表 { 和 } 。但是其他常用转义字符与 C 语言里的转义字符一样,都是反斜杠开头的形式。
```rust
fn main() {
println!("{{}}");
}
```
以上程序的输出结果是:
```shell
{}
```
# Rust 基础语法
变量,基本类型,函数,注释和控制流,这些几乎是每种编程语言都具有的编程概念。
这些基础概念将存在于每个 Rust 程序中,及早学习它们将使你以最快的速度学习 Rust 的使用。
## 变量
首先必须说明Rust 是强类型语言,但具有自动判断变量类型的能力。这很容易让人与弱类型语言产生混淆。
如果要声明变量,需要使用 `let` 关键字。例如:
```rust
let a = 123;
```
只学习过 JavaScript 的开发者对这句话很敏感,只学习过 C 语言的开发者对这句话很不理解。
在这句声明语句之后,以下三行代码都是被禁止的:
```rust
a = "abc";
a = 4.56;
a = 456;
```
第一行的错误在于当声明 a 是 123 以后a 就被确定为整型数字,不能把字符串类型的值赋给它。
第二行的错误在于自动转换数字精度有损失Rust 语言不允许精度有损失的自动数据类型转换。
第三行的错误在于 a 不是个可变变量。
前两种错误很容易理解,但第三个是什么意思?难道 a 不是个变量吗?
这就牵扯到了 Rust 语言为了高并发安全而做的设计:在语言层面尽量少的让变量的值可以改变。所以 a 的值不可变。但这不意味着 a 不是"变量"(英文中的 variable官方文档称 a 这种变量为"不可变变量"。
如果我们编写的程序的一部分在假设值永远不会改变的情况下运行,而我们代码的另一部分在改变该值,那么代码的第一部分可能就不会按照设计的意图去运转。由于这种原因造成的错误很难在事后找到。这是 Rust 语言设计这种机制的原因。
当然,使变量变得"可变"mutable只需一个 `mut`关键字。
```rust
let mut a = 123;
a = 456;
```
这个程序是正确的。
## 常量与不可变变量的区别
既然不可变变量是不可变的,那不就是常量吗?为什么叫变量?
变量和常量还是有区别的。在 Rust 中,以下程序是合法的:
```rust
let a = 123; // 可以编译,但可能有警告,因为该变量没有被使用
let a = 456;
```