中文官网下载:https://www.rust-lang.org/zh-CN/tools/install
中文官网文档:https://www.rust-lang.org/zh-CN/learn
Rust是一种快速、高并发、安全且具有授权性,最初由 Graydon Hoare 于2006年创造和发布。现在它是一种开源语言,主要由 Mozilla 团队和许多开源社区成员共同维护和开发。它的目标是 C 和 C++ 占主导地位的系统编程领域。
优势
Rust 是一门编译语言,因此它的效率可以媲美 C 或 C++ 语言
由于没有 GC(垃圾回收机制),所以是安全级高的语言
Rust 可以做什么?
安装Rust
Windows
下载并运行 rustup-init.exe
Linux or Mac:
curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh
另外,你还需要一个 链接器(linker),这是 Rust 用来将其编译的输出连接到一个文件中的程 序。很可能你已经有一个了。如果你遇到了链接器错误,请尝试安装一个 C 编译器,它通常包括 一个链接器。C 编译器也很有用,因为一些常见的 Rust 包依赖于 C 代码,因此需要安装一个 C 编 译器。
在 macOS 上,你可以通过运行以下命令获得 C 语言编译器:
xcode-select --install
Linux 用户通常需要根据发行版(distribution)文档安装 GCC 或 Clang。比如,如果你使用 Ubuntu,可以安装 build-essential 包
Windows 的 Linux 子系统(WSL)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
检查安装是否正确
要检查是否正确安装了 Rust,打开命令行并输入:
rustc --version
应该可以看到按照以下格式显示的最新稳定版本的版本号、对应的 Commit Hash 和 Commit 日期:
rustc x.y.z (abcabcabc yyyy-mm-dd)
如果看到了这样的信息,就说明 Rust 已经安装成功了!
如果没看到,请按照下面说明的方法检查 Rust 是否在您的 %PATH% 系统变量中
在 Rust 开发环境中,所有工具都安装在
~/.cargo/bin
目录中,您可以在这里找到包括rustc
、cargo
和rustup
在内的 Rust 工具链
echo %PATH% // windows
echo $env:Path // windows PowerShell
echo $PATH // Linux or macOS
更新与卸载
通过 rustup 安装了 Rust 之后,很容易更新到最新版本,只需要在命令行中运行
rustup update
若要卸载 Rust 和 rustup ,请在命令行中运行
rustup self uninstall
本地文档
安装程序也自带一份文档的本地拷贝,可以离线阅读。运行 rustup doc 在浏览器中查看本地文档
编译和运行是单独的两步
运行Rust程序之前必须先编译,命令为:rustc 源文件名
rustc
main.rs
编译成功后,会生成一个二进制文件
在Windows上还会生成一个
.pdb
文件,里面包含调试信息
Rust 是 ahead-of-time 编译的语言
可以先编译程序,然后把可以执行文件交给别人运行(无需安装Rust)
rustc
只适合简单的 Rust 程序
VS Code
VSCode(全称:Visual Studio Code)是一款由微软开发且跨平台的免费源代码编辑器,VSCode 开发环境非常简单易用。
下载地址:https://code.visualstudio.com/
官方文档地址:https://code.visualstudio.com/docs
安装插件:
rust-analyzer:语言服务器、自动补全、语法高亮
IntelliJ Rust
下载地址:https://www.jetbrains.com/rust/
安装 Rust 插件
Clion
下载地址:https://www.jetbrains.com/clion/
安装 Rust 插件
Cargo 是 Rust 的构建系统和包管理工具
cargo new holle_world
会创建一个新的目录 xxx (项目名也是),将会看到 Cargo 生成了两个文件和一个目录:一个 Cargo.toml
文件,一个 src
目录,一个 .gitignore
文件,以及位于 src
目录中的 main.rs
文件
Cargo.toml
TOML(Tom’s Obvious, Minimal Language) 格式,是 Cargo 的配置格式
[package] 是一个区域标题,表示下方内容是用来配置包(package)的
name,项目名
version,项目版本
authors,项目作者
edition,使用的 Rust 版本
[dependencies] 另一个区域的开始,它会列出项目的依赖项
在 Rust 里面,代码的包称作 crate
[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]
src
源文件
源代码都在 src
目录下
顶层目录可以放置:README、许可信息、配置文件和其它与程序源码无关的文件
如果创建项目时没有使用 cargo ,也可以把项目转化为使用 cargo:
把源代码文件移动到
src
下创建
Cargo.toml
并填写相应的配置
初始化一个新的Git仓库.gitignore
cargo new
的时候使用 --vcs
这个 flag注意:
Git 是一个常用的版本控制系统(version control system, VCS)。可以通过 – vcs 参数使 cargo new 切换到其它版本控制系统(VCS),或者不使用 VCS。运行 cargo new --help 参看可用的选项
cargo build
第一次运行 cargo build 会在顶层目录生成 cargo.toml
文件
cargo run
cargo run,编译代码 + 执行结果
cargo check
cargo check,检查代码,确保能通过编译,但是不产生任何可执行文件
在不生成二进制文件的情况下构建项目来检查错误
cargo check 要比 cargo build 快
cargo build --release
当项目最终准备好发布时,可以使用cargo build --release
来优化编译项目,会在 target/release 而不是 target/debug 生成可执行文件。如果你在测试代码的运行时间,请确保运行 cargo build – release 并使用 target/release 下的可执行文件进行测试
两种不同的配置:
猜数游戏
要创建一个新项目,进入第一章中创建的 projects 目录,使用 Cargo 新建一个项目,如下:
cargo new guessing_game
cd guessing_game
在 Cargo.toml
文件下的 [dependencies] 后添加 rand 库需要指定版本号
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.7.3"
use std::{io, cmp::Ordering}; // prelude
use rand::Rng; // trait
fn main() {
println!("猜数!");
let secret_number = rand::thread_rng().gen_range(1..=100);
// println!("神秘数字是:{}", secret_number);
loop {
println!("猜测一个数!");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("无法读取行");
let guess:u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
println!("你猜测的数是:{}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
关键字
目前正在使用的关键字
as
- 强制类型转换,消除特定包含项的 trait 的歧义,或者对 use
语句中的项重命名async
- 返回一个 Future
而不是阻塞当前线程await
- 暂停执行直到 Future
的结果就绪break
- 立刻退出循环const
- 定义常量或不变裸指针(constant raw pointer)continue
- 继续进入下一次循环迭代crate
- 在模块路径中,代指 crate rootdyn
- 动态分发 trait 对象else
- 作为 if
和 if let
控制流结构的 fallbackenum
- 定义一个枚举extern
- 链接一个外部函数或变量false
- 布尔字面值 false
fn
- 定义一个函数或 函数指针类型 (function pointer type)for
- 遍历一个迭代器或实现一个 trait 或者指定一个更高级的生命周期if
- 基于条件表达式的结果分支impl
- 实现自有或 trait 功能in
- for
循环语法的一部分let
- 绑定一个变量loop
- 无条件循环match
- 模式匹配mod
- 定义一个模块move
- 使闭包获取其所捕获项的所有权mut
- 表示引用、裸指针或模式绑定的可变性pub
- 表示结构体字段、impl
块或模块的公有可见性ref
- 通过引用绑定return
- 从函数中返回Self
- 定义或实现 trait 的类型的类型别名self
- 表示方法本身或当前模块static
- 表示全局变量或在整个程序执行期间保持其生命周期struct
- 定义一个结构体super
- 表示当前模块的父模块trait
- 定义一个 traittrue
- 布尔字面值 true
type
- 定义一个类型别名或关联类型union
- 定义一个 union 并且是 union 声明中唯一用到的关键字unsafe
- 表示不安全的代码、函数、trait 或实现use
- 引入外部空间的符号where
- 表示一个约束类型的从句while
- 基于一个表达式的结果判断是否进行循环保留做将来使用的关键字
如下关键字没有任何功能,不过由 Rust 保留以备将来的应用
abstract
become
box
do
final
macro
override
priv
try
typeof
unsized
virtual
yield
声明变量使用 let 关键字
默认情况下,变量是不可变的(Immutable)
声明变量时,在变量前面加上 mut
,就可以使变量可变
fn main() {
let mut x = 5;
println!("The value of x is {}", x);
x = 6;
println!("The value of x is {}", x);
}
常量
static:具有 ‘static 生命周期的,可以是可变的变量(须使用 static mut
关键字)
有个特例就是 “string” 字面量。它可以不经改动就被赋给一个 static 变量,因为它 的类型标记:&’static str 就包含了所要求的生命周期 ‘static。其他的引用类型都 必须特地声明,使之拥有’static 生命周期。
常量(constant),常量在绑定值以后也是不可变的,但是它与不可变的变量有很多区别:
不可以使用
mut
,常量永远都是不可变的声明常量使用
const
关键字,它的类型必须被标注常量可以在任何作用域内进行声明,包括全局作用域
常量只可以绑定到常量表达式,无法绑定到函数的调用结果或只能在运行时才能计算出的值
在程序运行时间,常量在其声明的作用域内一直有效
命名规范:Rust 里常量使用全大写字母,每个单词之间用下划线分开,
const MAX_POINTS:u32 = 100_000;
Shadowing(隐藏)
可以使用相同的名字声明新的变量,新的变量就会 shadow(隐藏)之前声明的同名变量
fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}
println!("The value of x is: {x}");
}
cargo run
Compiling variables v0.1.0 (file:///projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.31s
Running `target/debug/variables`
The value of x in the inner scope is: 12
The value of x is: 6
shadow 和把变量标记为 mut
是不一样的:
如果不使用 let 关键字,那么重新给非 mut
的变量赋值会导致编译时错误
而使用 let 声明的同名新变量,也是不可变的
使用 let 声明的同名新变量,它的类型可以与之前不同
fn main() {
let spaces = " ";
let spaces = spaces.len();
println!("{}", spaces);
}