目录
Rust
一门赋予每个人构建可靠且高效软件能力的语言
Rust 程序设计语言 一门赋予每个人构建可靠且高效软件能力的语言。https://www.rust-lang.org/zh-CN/
安装
官方下载网址:
安装 Rust - Rust 程序设计语言 一门赋予每个人构建可靠且高效软件能力的语言。https://www.rust-lang.org/zh-CN/tools/install安装 Rust 需要C++生成工具的支持,Visual Studio2017+版本以上都可以。
尝试
hello, world
-
fn
main() {
-
println!(
"hello, world");
-
}
创建一个后缀为 .rs 的源码文本文件 hello.rs,然后用Rust编译成一个可执行文件;也可以把源码直接粘贴到官方提供的在线编译器内执行。
为什么学习众多编程语言的第一个程序都是 hello, world ?
hello world 的起源
追溯到1972年,贝尔实验室著名研究员Brian Kernighan在撰写“B语言教程与指导(Tutorial Introduction to the Language B)”时初次使用(程序),这是目前已知最早的在计算机著作中将hello和world一起使用的记录。之后,在1978年,他在他和Dennis Ritchie合作撰写的C语言圣经“The C Programming Language”中,延用了“hello,world”句式,作为开篇第一个程序。在这个程序里,输出的”hello,world”全部是小写,没有感叹号,逗号后有一空格。虽然之后几乎没能流传下来这个最初的格式,但从此用hello world向世界打招呼成为惯例。几乎每一个程序设计语言的教材中的第一个范例都是hello world程序,因此在学习一门新语言的时候用hello world作为起步已经成为计算机程序界的一个传统。
编译
在cmd窗口下,把源码文件 hello.rs 编译,然后执行。
D:\Rust\hello>rustc hello.rs D:\Rust\hello>hello hello, world
链接出错
当编译发生以下报错时,说明生成工具没有安装成功
-
D:\Rust\hello\src>rustc main.rs
-
error: linker `link.exe` not found
-
|
-
= note: program not found
-
-
note: the msvc targets depend on the msvc linker but `link.exe` was not found
-
-
note: please ensure that Visual Studio
2017 or later, or Build Tools
for
Visual
-
Studio were installed with the Visual C++ option.
-
-
note: VS Code is a different product, and is not sufficient.
-
-
error: aborting due to previous error
执行以下2条命令进行修复
D:\Rust\hello>rustup toolchain install stable-x86_64-pc-windows-gnu D:\Rust\hello>rustup default stable-x86_64-pc-windows-gnu
开启 Rust 之旅
官方教程
官方网站网提供了2本基础教程以及众多文档,入门零成本,基本用不上买纸质书,省钱。
《Rust 程序设计语言》
被亲切地称为“圣经”。本书从基础出发,给出了 Rust 语言的概览。您将在阅读本书的过程中构建几个项目,读完本书后,您就能扎实地掌握 Rust 语言。
https://doc.rust-lang.org/book/
《通过例子学 Rust》
如果您不喜欢阅读大量的文档来学习语言,那么此书就能涵盖您要学的知识。虽然本书花了很多篇幅来解释代码,但它展示的代码很丰富,并且尽量减少了文字解释。它还包括很多练习!
https://doc.rust-lang.org/rust-by-example/
核心文档
以下所有文档都可以用 rustup doc 命令在本地阅读,它会在您的浏览器中离线打开这些资源!
标准库
版本指南
Rust 版本指南。
CARGO 手册
Rust 的包管理器和构建系统。
RUSTDOC 手册
学习如何为您的 crate 编写完美的文档。
RUSTC 手册
熟悉 Rust 编译器中可用的选项。
编译错误索引表
深入解释了您可能会遇到的编译错误。
非官方翻译教程
Rust 程序设计语言 简体中文版
- 简介
- 1. 入门指南
- 2. 写个猜数字游戏
- 3. 常见编程概念
- 4. 认识所有权
- 5. 使用结构体组织相关联的数据
- 6. 枚举和模式匹配
- 7. 使用包、Crate 和模块管理不断增长的项目
- 8. 常见集合
- 9. 错误处理
- 10. 泛型、Trait 和生命周期
- 11. 编写自动化测试
- 12. 一个 I/O 项目:构建命令行程序
- 13. Rust 中的函数式语言功能:迭代器与闭包
- 14. 更多关于 Cargo 和 Crates.io 的内容
- 15. 智能指针
- 16. 无畏并发
- 17. Rust 的面向对象编程特性
- 18. 模式与模式匹配
- 19. 高级特征
- 20. 最后的项目:构建多线程 web server
- 21. 附录
通过例子学 Rust 中文版
- 1. Hello World
- 2. 原生类型
- 3. 自定义类型
- 4. 变量绑定
- 5. 类型系统
- 6. 类型转换
- 7. 表达式
- 8. 流程控制
- 9. 函数
- 10. 模块
- 11. crate
- 12. cargo
- 13. 属性
- 14. 泛型
- 15. 作用域规则
- 16. 特质 trait
- 17. 使用 macro_rules! 来创建宏
- 18. 错误处理
- 19. 标准库类型
- 20. 标准库更多介绍
- 21. 测试
- 22. 不安全操作
- 23. 兼容性
- 24. 补充
有编程基础的大概浏览一遍,很快就能上手了
语法基础
变量和数据类型
在 Rust 中,变量可以通过 let
关键字进行声明和初始化。例如:
-
let x
=
5;
-
let y: i
32
=
10;
第一行代码定义了一个名为 x
的变量,其类型为 Rust 推断得到的整数类型。第二行代码定义了一个名为 y
的变量,并明确指定其类型为 i32
整数类型。
Rust 中的数据类型包括数字、字符、布尔值、字符串等。其中,数字类型包括整数和浮点数,可以用 i8
、i16
、i32
、i64
、u8
、u16
、u32
、u64
、f32
、f64
等类型进行声明。而布尔值则用 bool
表示,取值为 true
或 false
。字符类型用 char
表示,由单引号包围,例如:
let c = 'C';
字符串类型用双引号包围,可以是非 ASCII 字符串,例如:
let s = "Hello, 世界!";
注意:let mut
变量赋值
let
和 let mut
声明变量时的区别在于后者声明的变量可变,而前者声明的变量为不可变。let
声明的变量不能再次被赋值,而 let mut
声明的变量可以被修改赋值。
复合数据结构
元组 (Tuple)
元组是将多个不同类型的值组合在一起形成一个新的复合类型。元组使用圆括号 ()
来定义,元素之间使用逗号 ,
隔开。元组可以通过模式匹配来解构。例如:
-
let
person: (
String,
usize,
f64) = (
String::
from(
"Alice"),
30,
6.0);
-
-
println!(
"{} is {} years old and {} feet tall.", person.
0, person.
1, person.
2);
数组 (Array)
数组是由同一类元素组成的数据集合。数组的长度在编译时就已经确定,不可改变。数组使用中括号 []
来定义。例如:
-
let
numbers: [
i32;
5] = [
1,
2,
3,
4,
5];
-
-
println!(
"The third element is {}.", numbers[
2]);
向量 (Vector)
向量是一种动态数组类型,可以在运行时动态地增加或减少其大小。Vector 可以存储任意类型的数据,并且支持快速随机访问元素、在末尾追加元素、在任意位置插入和删除元素等操作。Vector 使用 Vec 类型来创建,例如:
-
let
mut
numbers:
Vec<
i32> =
vec![
1,
2,
3,
4,
5];
-
-
// 访问某个元素
-
println!(
"The third element is {}.", numbers[
2]);
-
-
// 在末尾追加元素
-
numbers.
push(
6);
-
-
// 插入元素到特定位置
-
numbers.
insert(
3,
10);
-
-
// 删除特定位置的元素
-
numbers.
remove(
2);
-
-
// 遍历所有元素
-
for
num
in &numbers {
-
println!(
"{}", num);
-
}
集合 (Set)
集合类型存储一组唯一的、无序的元素。Set 具有高效地判定元素是否存在的功能,但是不支持对元素的随机访问和插入。Set 使用 HashSet 类型来创建,例如:
-
use std::collections::HashSet;
-
-
let
mut
colors = HashSet::
new();
-
-
// 插入元素
-
colors.
insert(
String::
from(
"red"));
-
colors.
insert(
String::
from(
"green"));
-
colors.
insert(
String::
from(
"blue"));
-
-
// 判断元素是否存在
-
if colors.
contains(
"red") {
-
println!(
"The set contains red.");
-
}
-
-
// 删除元素
-
colors.
remove(
"green");
-
-
// 遍历所有元素
-
for
color
in &colors {
-
println!(
"{}", color);
-
}
结构体 (Struct)
结构体是一种自定义类型,可以包含不同类型的字段。通过在结构体中定义多个字段,可以将它们组合成一个单独的数据类型。结构体使用 struct
关键字来定义,字段可以是不同的类型,并且也可以包含其他的结构体。例如:
-
struct
Person {
-
name:
String,
-
age:
usize,
-
height:
f64,
-
}
-
-
let
alice = Person {
-
name:
String::
from(
"Alice"),
-
age:
30,
-
height:
6.0,
-
};
-
-
println!(
"{} is {} years old and {} feet tall.", alice.name, alice.age, alice.height);
关键字
-
as
const
else
enum
extern
-
false
fn
for
if
impl
-
in
let
loop
match
mod
-
move
mut
pub
ref
return
-
Self
self
static
struct
super
-
trait
true
type
unsafe
use
-
where
while
abstract
become
box
-
do
final
macro
override
priv
-
typeof
unsized
virtual
yield
这些关键字具有不同的含义和用法,例如:
fn
: 声明一个函数let
: 声明一个变量if
、else
、for
、while
等: 分别表示条件语句、循环语句match
: 匹配表达式的值与模式mod
、use
: 分别表示模块声明与模块引用struct
、enum
、trait
、impl
等: 分别表示结构体、枚举类型、特质、实现等
在 Rust 中,使用这些关键字需要注意避免与现有标识符冲突。如果需要使用与关键字同名的标识符,则可以使用反引号
将标识符括起来,例如:
-
let `
match` =
3;
-
println!(
"the value of match is {}", `
match`);
以上代码中,用反引号括起来的 match
可以作为变量名使用,但是不推荐这么做,因为会让代码不够清晰。
控制语句
Rust 支持常见的控制流语句,包括条件语句、循环语句和匹配语句等。
条件语句
用 if
和 else
关键字表示,例如:
-
let x
=
10;
-
if x
<
0 {
-
println!(
"x is negative");
-
}
else
if x
>
0 {
-
println!(
"x is positive");
-
}
else {
-
println!(
"x is zero");
-
}
循环语句
用 loop
、while
和 for
关键字表示,例如:
-
let mut x
=
0;
-
loop {
-
x
+
=
1;
-
if x
=
=
10 {
-
break;
-
}
-
}
-
println!(
"x is {}", x);
-
-
let mut y
=
0;
-
while y
<
10 {
-
y
+
=
1;
-
}
-
println!(
"y is {}", y);
-
-
let a
= [
1,
2,
3,
4,
5];
-
for element
in a.iter() {
-
println!(
"element is {}", element);
-
}
匹配语句
用 match
关键字表示,可以根据不同的值匹配执行不同的代码块。例如:
-
let x
=
5;
-
match x {
-
1
=
> println!(
"x is one"),
-
2 |
3 |
4
=
> println!(
"x is two or three or four"),
-
/
/ 匹配任何其他数字
-
_
=
> println!(
"x is {}", x),
-
}
函数
Rust 中的函数可以通过 fn
关键字进行定义,例如:
-
fn
add(x:
i32, y:
i32)
->
i32 {
-
x + y
-
}
-
-
fn
main() {
-
let
a =
add(
1,
2);
-
let
b =
add(
2,
3);
-
println!(
"{}\n{}", a, b);
-
}
该函数接受两个 i32
参数 x
和 y
,返回它们的和。
函数的最后一个表达式被视为返回值,这与其它大多数语言不同:可以省去 return 关键字。
Rust 支持函数的默认参数和可变参数,例如:
-
fn
mul(x:
i32, y:
i32, z:
i32)
->
i32 {
-
return x * y * z
-
}
-
-
fn
div(x:
f32, y:
f32)
->
f32 {
-
if y ==
0.0 {
-
panic!(
"division by zero");
-
}
-
return x / y
-
}
-
-
fn
print(words: &
str, times:
i32) {
-
for
_
in
0..times {
-
println!(
"{}", words);
-
}
-
}
-
-
fn
main() {
-
let
a =
mul(
1,
2,
3);
-
let
b =
div(
10.0,
3.0);
-
let
c =
"hello";
-
println!(
"{}\n{}", a, b);
-
print(c,
3);
-
}
Rust 也支持泛型类型参数,例如:
-
fn
add<T: std::ops::Add<Output=T>>(x: T, y: T)
-> T {
-
x + y
-
}
-
-
fn
foo<T>(x: T)
-> T {
-
x
-
}
-
-
fn
main() {
-
let
a =
add(
1,
2);
-
let
b =
add(
2.0,
3.0);
-
println!(
"{}\n{}\n", a, b);
-
-
let
a =
foo(
1);
// a 为整数类型
-
let
b =
foo(
"hello");
// b 是字符串类型
-
let
c =
foo(
vec![
1,
2,
3]);
// c 是一个整数向量类型
-
println!(
"{}\n{}\n{:?}", a, b, c);
-
}
模块
模块是 Rust 中的一种隔离和组织代码的方式,其可以分为本地模块和外部模块。本地模块用 mod
关键字表示,用于组织和封装代码,例如:
-
mod math {
-
fn
add(x: i
32, y: i
32) -
> i
32 {
-
x
+ y
-
}
-
-
pub fn sub(x: i
32, y: i
32) -
> i
32 {
-
x
- y
-
}
-
}
该代码中,定义了一个 math
模块和其中的两个函数 add
和 sub
。其中,函数 add
是私有的,只能在模块内部使用,而函数 sub
是公有的,可以在其他模块中使用。
除了本地模块之外,Rust 还支持使用 extern crate
加载外部依赖库,并通过 use
关键字引用其模块、类型和函数等。例如:
-
extern crate rand;
-
-
use rand
::Rng;
-
-
fn main() {
-
let mut rng
= rand
::thread_rng();
-
let n: i
32
= rng.gen_range(
1,
7);
-
println!(
"the random number is: {}", n);
-
}
以上就是 Rust 语言的基础语法介绍,包括变量和数据类型、控制流、函数和模块等内容。Rust 相比于其他语言,具有更加严格的类型检查和所有权规则等特性,可以保证代码的内存安全和高效运行。
代码实例
1. 两数之和
-
use std::collections::HashMap;
-
-
fn
two_sum(nums:
Vec<
i32>, target:
i32)
->
Vec<
i32> {
-
let
mut
map = HashMap::
new();
-
for (i, &num)
in nums.
iter().
enumerate() {
-
if
let
Some(&j) = map.
get(&(target - num)) {
-
return
vec![j
as
i32, i
as
i32];
-
}
-
map.
insert(num, i);
-
}
-
vec![]
-
}
-
-
fn
main() {
-
let
nums =
vec![
2,
7,
11,
15];
-
let
target =
9;
-
let
result =
two_sum(nums, target);
-
println!(
"{:?}", result);
// 输出 [0, 1]
-
}
2. 最长子串
-
pub
fn
length_of_longest_substring(s:
String)
->
i32 {
-
let
mut
chars = s.
chars();
-
let
mut
map = std::collections::HashMap::
new();
-
let
mut
max_length =
0;
-
let
mut
start =
0;
-
let
mut
end =
0;
-
while
let
Some(c) = chars.
next() {
-
if
let
Some(index) = map.
get(&c) {
-
start = start.
max(*index +
1);
-
}
-
end +=
1;
-
map.
insert(c, end -
1);
-
max_length = max_length.
max(end - start);
-
}
-
max_length
as
i32
-
}
-
-
fn
main() {
-
let
s =
String::
from(
"abcabcbb");
-
let
result =
length_of_longest_substring(s);
-
println!(
"{}", result);
-
let
s =
String::
from(
"bbbbb");
-
let
result =
length_of_longest_substring(s);
-
println!(
"{}", result);
-
let
s =
String::
from(
"pwwkew");
-
let
result =
length_of_longest_substring(s);
-
println!(
"{}", result);
-
}
3. 反转整数
-
pub
fn
reverse(x:
i32)
->
i32 {
-
let
mut
x = x;
-
let
mut
res =
0;
-
while x !=
0 {
-
let
pop = x %
10;
-
x /=
10;
-
if res > std::
i32::MAX /
10 || (res == std::
i32::MAX /
10 && pop >
7) {
-
return
0;
-
}
-
if res < std::
i32::MIN /
10 || (res == std::
i32::MIN /
10 && pop < -
8) {
-
return
0;
-
}
-
res = res *
10 + pop;
-
}
-
res
-
}
-
-
fn
main() {
-
let
x =
123;
-
println!(
"{}",
reverse(x));
-
let
x = -
123;
-
println!(
"{}",
reverse(x));
-
let
x =
120;
-
println!(
"{}",
reverse(x));
-
}
2023.5.3