一、安装

Linux

Linux 安装非常简单,只需要一行命令:

Window

也可以不按照下面的步骤,直接使用 RUST-INIT 安装的时候它也会让你先安装这个环境(根据提示选对吼),并且已经自动帮你勾选、添加环境变量等操作,你需要做的只是 waiting。

下载 Microsoft C++ Build Tools,勾选 C++ 环境和自己的操作系统的 SDK,如下图所示。

安装的文件比较大,建议手动选择安装位置,避免占用过多系统盘。等待安装完成后,然后找到程序安装的位置:%Visual Studio 安装位置%\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\%version%\bin\Hostx64\x64,把该值添加到环境变量中。

%Visual Studio 安装位置%%version% 需要替换自己的安装路径和对应的版本号。

以上工作完成后就可以下载 RUST-INIT 并双击运行,默认回车等待安装完毕。

crates 国内下载源

由于 crates.io 的下载速度较慢,我们需要使用国内的源来下载第三方库。编辑文件 $HOME/.cargo/config.toml(Rust 版本 <= 1.38 时使用 config 文件),如果没有该文件,手动创建即可。

Rust 1.68 之后推荐使用稀疏索引,避免完整 clone,加快下载更新速度。

~/.cargo/config.toml
1
2
3
4
5
[source.crates-io]
replace-with = 'ustc'

[source.ustc]
registry = "sparse+https://mirrors.ustc.edu.cn/crates.io-index/"

Rust 一些命令

Rust 自带了非常完善的工具链:Cargo,Cargo 是 Rust 的构建系统和包管理器。

虽然 Cargo 的部分命令可以使用 rustc 来代替(你可以把 cargo 看作是 rustc 的高级封装),但是一旦涉及到依赖管理或者其它高级使用的问题,rustc 就相形见绌了,本文不详细介绍 rustc 的相关命令,这里放一个链接:https://doc.rust-lang.org/rustc/what-is-rustc.html,有需要自行查看。

Cargo 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# cargo 帮助
cargo --help
# 查看 Rust 版本
cargo --version
# 创建新的 hello_cargo 项目
cargo new hello_cargo
# 初始化当前的目录为 Rust 项目
cargo init
# 构建项目
cargo build
# 构建并运行项目
cargo run
# 检查代码,确保其可编译但不生成可执行文件(速度快)
cargo check
# 运行项目中的测试
cargo test
# 构建项目文档,并直接打开文档
cargo doc --open

cargo 将构建的二进制执行文件放在 target/debug 目录中,与项目同名.
当你的项目准备发布时,建议使用 cargo build --release 进行优化,这些优化使你的 Rust 代码运行得更快,但会延长程序编译所需的时间。此命令将在 target/release 中创建可执行文件.
如果要对代码的运行时间进行基准测试,请务必运行 cargo build --release 并使用 target/release 中的可执行文件进行基准测试.

执行命令时,cargo 会检查代码中未使用的变量和方法并输出警告。如果这些变量和方法需要临时保留,同时不想让编译器给出警告,可以在未使用的变量和方法上加入 _ 前缀。另外还有一些注解辅助禁止警告。

  • #[warn(dead_code)] 标注可以消除编译器对于没有用到的代码的警告;
  • #[warn(unused_imports)] 标注可以消除对已经导入但未使用包的警告;

版本更新

1
2
# 更新 Rust 版本
rustup update

Rust 的依赖管理

Rust 项目的文件管理清单都在 Cargo.toml 中,该清单包括项目基本信息(例如作者、仓库地址、rust版本等)、依赖(包括构建依赖、开发依赖等)等信息。如果你还不熟悉 Toml 的配置方式,可以学习一下,比较简单。

Rust 的依赖搜索可以去 crates.io 中查询,类似与 Maven 的中央仓库。

截至目前,新建的 Rust 项目中的 Cargo.toml 中默认包含以下信息:

Cargo.toml
1
2
3
4
5
6
7
8
9
10
# 项目的描述信息
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

# 依赖
[dependencies]

初步简单认识 cargo workspace

如果所构建的项目较大,那么可以使用 cargo workspace。和多模块有点儿类似。

rust_parent 为例,作为顶级目录,父母录中的 Cargo.toml 配置子包的目录名称即可。

1
cargo new rust_parent && cd rust_parent

然后打开 Cargo.toml 文件,删除所有内容,添加以下内容:

Cargo.toml
1
2
3
4
5
6
7
[workspace]

# 子包目录名称
members = [
"sub1",
"....",
]

然后我们创建子包:

1
cargo new sub1

之后运行 cargo build 目录应如下所示:

1
2
3
4
5
6
7
8
── rust_parent
├── Cargo.lock
├── Cargo.toml
├── sub1
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target

无论有多少 crate,都只会在顶层目录的 target 中输出二进制文件。
如果要单独运行某个包中的程序,使用 cargo run -p [package],例如 cargo run -p sub1

二、Rust 命名规则

任何一门编程语言,都有对应的命名规范,开发时遵守规范利于他人阅读、维护。Rust 也不例外。命名规则参考 Rust 语言圣经:https://course.rs/practice/naming.html

三、初步认识

  • Rust 的标准库小而稳定,只提供语法特性,扩展较强,所以大部分时候都要使用 cargo 引入并管理依赖,cargo 也支持自定义扩展命令也是因此。

  • Rust 的生态很多内容都是通过社区提供支持的。

  • Rust 中,只有实现了 std::fmt::Display trait 的自定义 struct 才可以自定义输出格式并且可以使用 {} 进行占位。如果使用 #[derive(Debug)] 进行标注,则使用 {:?} 或者 {:#?} 美化输出。

  • Rust 中的属性定义和方法是分离的,方法或者函数放置在 impl 块中,便于维护、格式清晰。如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 自定义结构体,实现 Debug trait 以便于使用 {:?} 进行打印输出
#[derive(Debug)]
struct Person {
name: String,
age: i32,
address: String,
hobby: Vec<String>
}

// 自定义类型结构体的方法
impl Person {

fn say(&self) -> Self{
todo!()
}

// 这种定义在 impl 中且没有 self 的函数被称之为关联函数
fn dance() {
todo!()
}
}

fn add(a: &str, b: &str) {

}

self 是当前的类型实例,Self 指代当前的类型,这是一种简单的编写方式。

在 Rust 中,如果方法返回类型不是 Self,并且没有包含泛型,使用这样的特征创建的对象被称为 安全的特征对象
Rust 函数的每一个引用参数都有自己的生命周期;如果函数只有一个引用类型的参数,那么该生命周期会同步作用到输出生命周期;若存在多个输入生命周期,且其中一个是 &self&mut self,则 &self 的生命周期被赋给所有的输出生命周期。

函数或者方法中,参数的生命周期被称为 输入生命周期,返回值的生命周期被称为 输出生命周期

Rust 智能指针

名称 简介 强项 弱项
Raw Point *mut T*const T,自由基,闪电般快,极其 unsafe 速度、与外界交互 Unsafe
Box<T> 可以把任何东西都放在 Box 中。可接受几乎任何类型的长期存储。新的安全编程时代的主力军 将值存在 Heap 大小增加
Rc<T> 是 Rust 的能干而吝啬的簿记员。他知道谁借了什么,何时借了什么 对值的共享访问 大小增加;
运行时不安全;
线程不安全
Arc<T> 是 Rust 的大使。它可以跨线程共享值,保证这些值不会相互干扰。 对值的共享访问;线程安全 大小增加;
运行时成本;
Cell<T> 变态专家,具有改变不可变值的能力 内部可变性; 大小增加;
性能;
RefCell<T> 对不可变引用执行改变,但有代价 内部可变性;可与仅接受不可变引用的 Rc、Arc 嵌套使用; 大小增加;
运行时成本;
缺乏编译时保障;
Cow (Copy on write) 封闭并提供对借用数据的不可变访问,并在需要修改或所有权时 延迟克隆数据 当只是只读访问时避免写入; 大小可能会增大;
String 处理可变长度的文本,展示了如何构建安全的抽象 动态按需增长;
在运行时保证正确编码;
过度分配内存大小;
Vec<T> 程序中最常用的存储系统,它在创建和销毁值时保持数据有序 动态按需增长; 过度分配内存大小;
RawVec<T> 是 Vec 和其它动态大小类型的基石,知道如何按需给你的数据提供一个家 动态按需增长;
与内存分配器一起配合寻找空间;
不直接适用于您的代码;
Unique<T> 作为值的唯一所有者,可保证拥有完全控制权 需要独占值的类型(如 String)的基础 不适合直接用于应用程序代码;
Shared<T> 分享所有权很难,但它使生活更轻松。 共享所有权;
可以将内存与 T 的宽度对齐,即使为空的时候;
不适合直接用于应用程序代码;

Drop Trait,智能指针的必备特征之一。

四、Rust 流行库


本站由 江湖浪子 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。