邂逅 Rust
学习Rust基础的第一天
安装Rust
Rust安装起来很方便,你可以使用 https://rustup.rs/ 给出的方法,根据你的操作系统进行安装。
vscode插件
- rust-analyzer:它会实时编译和分析你的 Rust 代码,提示代码中的错误,并对类型进行标注。你也可以使用官方的 Rust 插件取代
- Rust syntax:为代码提供高亮
- Dependi: 帮助你分析当前项目的依赖是否是最新的版本
- Even Better TOML:Rust使用toml做项目的配置管理。better toml可以帮你语法高亮,并展示toml中的错误
- Rust test lens:可以帮你快速运行某个Rust测试
- Tabnine:基于AI的自动补全,可以帮助你更快地撰写代码。
案例练习
通过使用htpp请求Rust官网首页,然后把获得的HTML转成Markdown保存
首先使用cargo new scrape_url
生成一个新的项目,默认情况下,这条命令会生成一个可执行项目scrape_url,入口文件在src/main.rs。我们在Cargo.toml里,加如下依赖
[dependencies]
reqwest = { version = "0.12", features = ["blocking"] }
html2md = "0.2"
Cargo.toml是Rust项目的配置管理文件,它符合toml语法。
我们这个项目添加了两个依赖:
- reqwest: htpp请求客户端
- html2md:把HTML文本转成Markdown
接下来,在src/main.rs里,我们为main()函数加入以下代码:
use std::fs;
fn main() {
let url = "https://www.rust-lang.org";
let output = "rust.md";
println!("发起网络请求:{}", url);
let body = reqwest::blocking::get(url).unwrap().text().unwrap();
println!("正在从hmtl转到markdown中...");
let md = html2md::parse_html(&body);
fs::write(output, md.as_bytes()).unwrap();
println!("转换完成,保存名称为:{} 保存在当前目录文件夹下", output);
}
运行成功后,可以在项目目录文件夹下看到rust.md,里面的内容就是从https://www.rust-lang.org获取到的html文本转换成markdown格式的结果。
案例总结
在这个项目中我们可以直观地感受到Rust的一些基本特点:
首先,Rust使用名为cargo的工具来管理项目,他类似Nodejs的npm用来做依赖管理以及开发过程中的任务管理,比如编译、运行、测试、代码格式化等等。
另外,你也容易看到,Rust虽然是一门强类型语言,但编译器支持类型推导,这使得写代码时的直观感受和写脚本差不多
这里例子没有展现出来,但Rust还具备的其他特点有:
Rust的变量默认是不可变的,如果要修变量值,需要显示地使用mut关键字。
除了let/static/con/fn等少数语句外,Rust绝大多数代码都是表达式。所以if/while/for/loop都会返回一个值,函数最后一个表达式就是函数的返回值,这和函数式编程语言一致。
基础语法和基础数据类型
首先我们看在Rust下,我们如何定Rust变量、函数和数据结构
变量和函数
前面说到,Rust支持类型推导,在编译器能够推导类型的情况下,变量类型一般可以省略,但常量(const),和静态变量(static)必须声明类型。
定义变量的时候,根据需要,你可以添加mut
关键字让变量变得具备可变性。默认变量不可变是一个重要的特性,有助于我们写出健壮且正确的代码。当你使用mut却没有修改变量,Rust编译器会友好地报警,提示你移除不必要的mut
。
在Rust下,函数是一等公民,可以作为参数或者返回值,我们来看一个函数作为参数的例子:
fn apply(value: i32, f: fn(i32) -> i32) -> i32 {
f(value)
}
fn square(value: i32) -> i32 {
value * value
}
fn cube(value: i32) -> i32 {
value * value * value
}
fn main() {
println!("apply square: {}", apply(2, square));
println!("apply cube: {}", apply(2, cube))
}
运行结果:
apply square: 4
apply cube: 8
代码中的fn(i32) -> 32
是apply函数第二个参数的类型,它表明接受一个函数作为参数,这个传入的函数必须是:参数只有一个。且类型为i32,返回值类型也是i32
Rust函数参数的类型和返回值类型都必须显示定义,如果没有返回值可以忽略,返回unit。函数内部如果提前返回,需要用return关键字,否则最后一个表达式就是其返回值。如果最后一个表达式后添加了;
分号,隐含其返回值为unit。可以看一下例子:
fn pi() -> f64 {
3.1415926
}
fn not_pi() {
3.1415926;
}
fn main() {
let is_pi = pi();
let is_unit1 = not_pi();
let is_unit2 = {
pi();
};
println!("is_pi: {:?}, is_unit1: {:?}, is_unit2: {:?}", is_pi, is_unit1, is_unit2);
}
运行结果:
is_pi: 3.1415926, is_unit1: (), is_unit2: ()