• rust也是一门编译语言,而且很新,是二零一几年出的一个语言。但是rust的内存管理非常的安全,而且有堪比C++的运行效率
  • 该rust学习笔记不适合纯新生或者是刚入门的新手,本人学习rust的主要目的是学习一下rust逆向和rust的pwn,更偏向于其内存管理等底层机制

rust环境

  • 一开始入门不打算用IDEA开发效率高的环境,想一行一行敲,感觉这样基础更牢,所以就在Linux下搭建了rust环境。
  • 在Linux下安装rust环境感觉是比在windows上容易的多,直接就是输入指令
1
2
3
sudo apt update
sudo apt install rustc
sudo apt install cargo
  • 下载好后查看安装结果
1
2
rustc --version
cargo --version

image-20241003090306555

  • 先创建并编写一个简单的rust程序,先创建main.rs文件,然后再编写如下内容
1
2
3
4
5
6
7
8
9
fn main(){
let a = 12;
println!("a is {0}",a);
println!("a is {},a again is {}",a,a);
println!("a is {0},a again is {a}",a);
println!("a is {{}}");
println!("this is a \n huan hang fu");
println!("look");
}
  • 使用rustc编译,rustc main.rs ,然后运行编译后的文件

image-20241003090616372

Cargo的使用

cargo介绍

  • Cargo是Rust编程语言的包管理系统和构建系统。它用于管理Rust项目的依赖项、编译代码、运行测试、构建项目和发布库。可以类似于Python的pip包管理器
  • 接下来介绍一下cargo的一些常用的命令

cargo new

  • 使用cargo启动新项目
1
2
3
4
5
6
7
cargo new 项目名 --bin   //创建一个可执行程序
cargo new hello_world --bin

cargo new 项目名 //编写一个可以被其他项目引用的库和包
cargo new hello_world

# 这两个命令其实没差,生成的效果都一样
  • 使用cargo new hello_world --bin,创建一个可执行程序它的目录如下
    • 其中Cargo.toml,是由Cargo生成的配置文件,用于定义项目的元数据、依赖性、编译配置等。
    • src:里面存放的是源代码,src里面会生成一个main.rs文件,.rs后缀的文件就是rust的源代码文件
1
2
3
4
hello_world
--Cargo.toml(文件)
--src(目录)
--main.rs
  • 接下来查看一些cargo.toml文件里面的具体信息,使用vim cargo.toml命令查看该文件里面的内容
    • name:表示包的名字
    • version:项目版本号
    • edition :Rust的版本
1
2
3
4
5
6
7
8
[package]
name = "hello_world1"
version = "0.1.0"
edition = "2021"

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

[dependencies]

注意:使用cargo new hello_wold命令生成的项目,目录也是与上方一样

cargo build

  • cargo build命令是编译使用cargo new所创建的项目
1
cargon build
  • 直接在所创建的项目内使用cargo build命令编译即可
1
2
3
4
5
myheart@aaa ~/c/r/hello_world1 (master)> ls
Cargo.toml src
myheart@aaa ~/c/r/hello_world1 (master)> cargo build
Compiling hello_world1 v0.1.0 (/home/myheart/code/rust/hello_world1)
Finished dev [unoptimized + debuginfo] target(s) in 0.92s
  • 使用cargo build命令后,项目的目录结构会发生改变,编译后基本上就是这样的目录,具体的了解即可。重点就是为可执行二进制文件
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
26
27
28
hello_world
--Cargo.lock(文件)
--Cargo.toml(文件)
--src(目录)
--main.rs(源代码)
--target(目录)
--CACHEDIR.TAG(文件)
--debug(目录)
--build(目录)
--deps(目录)
--hello_world-65c478c245451323
--hello_world-65c478c245451323.d
--examples(目录)
--hello_world(可执行二进制文件)
--hello_world.d(文件)
--incremental(目录)
--hello_world-2raufob2y547t(目录)
--s-h1czdyejl1-16wthvs-37ja4u7549aastc5b8qe1nrmn(目录)
--24qepgxx259x3ntg.o
--4hcybahg0o19qhm4.o
--2i7b77ao4v5unib8.o
--540zf6nxv88tkrze.o
--3ohs3puklkwxl3d3.o
--c4bpplywo62iusm.o
--dep-graph.bin
--query-cache.bin
--work-products.bin
--s-h1czdyejl1-16wthvs.lock(文件)

rust hello_world

内容

  • 首先先来一个hello_wrold
1
2
3
fn main(){
println!("hello world!");
}
  • 使用cargo build,将该源代码编译,也可以直接使用rustc编译编译,使用rustc ./main.rs
  • 编译后运行即可就会出现如下输出:
1
2
myheart@aaa ~/c/r/h/src (master)> ./main
hello world!
  • 接下来分析一下该程序:
  • 首先fn main()
    • fn定义函数的关键字
    • main(),就代表main函数,当运行该程序的时候,该程序就会从main函数这边开始运行
    • 如果声明函数的要参数的话,该参数必须在()内部被声明
    • {}花括号就是函数体,rust要求所有函数体都要被花括号包裹起来
1
2
fn main(){
}
  • 然后println!()函数:这个是输出函数,即打印函数,会将字符给打印到屏幕中。
    • 在这里需要强调:rust风格使用四个空格进行缩进,而不是使用Tab键
    • 然后println!是一个宏,如果单纯调用一个函数,那么就不会有!,即正常函数是这样的println()
    • rust中所有以!结尾的调用都意味着是使用宏而不是普通的函数
    • 然后rust代码行都会以分号来结尾。
1
println!(“hello world!”);

总结

  • 关于rust编程风格
    • rust要使用fn关键字定义函数
    • rust要使用{}来表示函数体,rust要求所有函数都要被花括号包裹起来
    • rust中缩进为四个空格,而不是Tap
    • rust代码行都会以分号来结尾;
    • rust中程序以main函数为程序的入口点
  • 补充一点:rust语言也是使用//表示单行注释,

项目-猜数字

创建项目

  • 接下来将编写一个猜数字的简单项目,利用该项目再来熟悉一下rust程序的编写

  • 先使用cargo创建一个guessing_game,进入该目录,cd guessing_game

1
cargo new guessing_game

image-20241031184226425

  • 然后我们先使用cargo run命令将该项目编译运行一下,该命令可以用于快速迭代一个项目

image-20241031185506727

编写项目

第一部分 基本结构

  • cargo run运行完之后就可以,可以使用编写程序了,编写main.rs
  • 该程序实现的是一个猜数字游戏,这是该游戏的第一部分,该部分会请求用户进行输入,并检查输入是否满足预期的格式。
1
2
3
4
5
6
7
8
9
10
11
12
13
use std::io;

fn main() {
println!("Guess the number!");

println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess).expect("Failed to read line");

println!("You guessed: {}",guess);
}
  • 写好后使用cargo run命令再编译运行该程序

image-20241031190149022

第一部分解释

导入包

  • use std::io,就是导入std标准库中的io模块,可以类比于Python的import io(虽然类比于C++会更合适)。
    • rust一开始会导入一些模块,该模块的作用域为每一段程序。这个导入的模块只包含了一小部分。
    • 但是有些函数或者类没有在该模块中我们就要使用use语句,导入其他的库和模块,就比如use std::io
    • std::io这个模块在该部分的作用是获得用户输入的数据,如果我们没有use std::io这个语句,当我们使用io::stdin时就不能这么写,而是要写成std::io::stdin

声明变量

  • let mut guess :该语句是声明一个可变的变量,let是声明一个变量guessmut(mutable)表示这个guess变量是可变的。并且程序会在栈内存中开辟一个空间,来存储guess变量的值。
  • 这里我们深刻来理解一下mut,这个使得变量可变的关键字
  • 当我们使用let foo = 5时,该变量是不可变的,即之后的代码中,我们不能再将foo赋值给其他值。这里我们进行一个lab。当我们使用rustc lab1.rs编译时,会出现如下的报错
1
2
3
4
fn main(){
let a = 5;
a = 6;
}

image-20241031194834895

  • 当我们使用let mun a=5时就可以对a进行修改
1
2
3
4
5
fn main() {
let mut a = 5;
a = 6;
println!("a 的值是: {}", a); // 使用变量 a
}
  • 这时我们再编译就只会出现警告,而不是报错,可以正常编译,编译后也能正常运行

image-20241031195248351

创建实例

  • let mut guess = String::new,该语句中String::new,会创建一个String的实例。
    • String是标准库中的一个字符串类型,它在内部使用UTF-8格式编码,并可以按需求扩展自己的大小
    • new是一个关联函数,并不是独立函数,它的作用创建某一类型的一实例。new会开辟一个堆内存空间,使用该函数开辟的堆内存空间是被自动管理的。并不需要我们手动管理
    • String::new,就是将字符串类型与new函数关联起来,开辟一个字符串类型的堆内存空间,返回的是一个字符串对象。可以用处理字符串的方法来处理该对象。
    • let mut guess = String::new,表示guess指向一个字符串对象,调用该变量可以打印出该字符串对象里面的字符串。

注意:可以简单理解guess指向该对象,但是并不是String::new返回值是单纯的堆地址,面向对象的内存管理抽象化了,是自动管理内存的。并不是像C语言那样将内存具体化,让开发者手动管理内存。(可以试着打印一些guess的值,它不会打印出地址,而是在该对象没有任何内容的时候会输出空。)

  • let mut guess = String::new,运行该语句的内存运行机制。面向对象的,可以看做是对结构体的一种扩展和运用。对于字符串这个对象,在rust语言中会是如下的结构体。而guess变量是指向一个字符串实例,所以guess变量存储着一个指针。
  • 而我们在一个对象中有特定的方法可以操作该对象,可以理解为有专门的函数可以处理该结构体。
1
2
3
4
5
struct String {
ptr: *mut u8, // 指向堆上数据的指针
len: usize, // 当前字符串的长度
capacity: usize // 当前分配的容量
}

image-20241101142003043

输入处理

  • io::stdin会返回std::io::stdin的实例,该实例中保存了许多方法来处理终端的标准输入。比如.read_line这个方法就是用来读取用户的一行标准输入
  • io::stdin().read_line(&mut guess),这行代码中.read_line(&mut guess)里面的&mut guess,是引用传参,&意味着当前参数是一个引用。
  • 引用操作的是与传递的参数同一块的内存,而不是像普通传参一样,复制一份对我们所复制的进行修改

注意:引用的参数与变量一样默认情况下是不可变的,所以我们需要使用mut关键字,表示该引用的参数是可变的

异常处理

  • io::stdin().read_line(&mut guess).expect("Failed to read line");这行代码其实是这么长
  • 当我们使用.read_line方法的时候,使用结束后该方法会返回io::Result的值,Result是一个枚举类型,拥有Ok(字母O)和Err两个变体。执行成功Result的值为Ok,而在执行过程中出错,就会Result的值就为Err,并且附带失败的原因
  • expect方法就是用来处理Result的这个枚举类型,当expect接收到为Err,那么就会中断程序,并将传入的字符串参数显示出来。如果接收到为OK那么就会提取OK中附带的值,并返回给用户。

注意:如果没有expect这种异常处理,仍然可以通过编译,但是编译器有警告提示

println!占位符

  • 最后这句println!("a 的值是: {}", a)可以将存储的用户输入打印出来。
  • 第一个参数是用来格式化字符串的,而花括号就相当于占位符{},可以将后面的参数值插入用{}所占的位置,第一个花括号对应的第一个参数,第二个花括号对应的是第二个参数,以此类推。
  • 接下来简单再来演示一下花括号的占位符,这个的字符串输出结果就会被变量aba+b的值给取代了。格式化字符串输出这个内部原理,可以上网了解一下C语言printf函数的内部实现。
1
2
3
4
5
fn main(){
let a = 10;
let b = 20;
println!("{}+{}={}",a,b,a+b);
}

image-20241101145541713

第二部分 随机数生成

  • 为了增加游戏的可玩性,我们将使用随机数来生成一个数字,然用户去猜测。
  • 在rust中,并没有把随机数生成函数,内置到标准库中,而是作为外部的rand包提供给用户
  • rust中的包(crate)代表了一系列源代码文件的集合
    • 我们当前正在构建的项目是一个用于生成可执行程序的二进制包
    • rand包是一个用于重复功能的库包
  • Cargo之前有说过类似于python中的pip,是用来帮助我们管理和使用第三方库和包,所以在使用rand这个包的时候就先要使用Cargo导入rand包。
  • 我们先在该目录下对Cargo.toml这个文件进行编辑

image-20241102101144682

  • dependencies下方导入rand包,即添加一行rand="0.3.14"
  • rand="0.3.14"表示任何与0.3.14版本公共API相兼容的版本

image-20241102101626089

  • 修改完保存后,不要修改任何rust代码,直接使用cargo build重构这个项目,Cargo就会下载rand包到本地中

image-20241102102257666

  • 接下来我们使用随机数,增加猜数字的趣味性和可玩性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use std::io;
use rand::Rng;

fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1,101);
println!("The secret number is: {}", secret_number);
println!("Please input your guess.");
let mut guess = String::new();

io::stdin().read_line(&mut guess).expect("Failed to read line");

println!("You guessed: {}",guess);
}

第二部分解释

  • use rand::Rng:这里的Rng是一个train(特征),它定义了随机数生成的方法集合,这使得我们可以访问随机数生成的方法。

  • let secret_number = rand::thread_rng().gen_range(1,101),这段代码中

    • rand::thread_rng()会返回一个特定的随机数生成器,位于本地线程空间,并通过操作系统获得随机数种子,之后就利用gen_range这个方法生成随机数
    • gen_range这个方法是接收俩个数字做为参数,并生成包含下限但是不包含上限的随机数,在本代码中参数为(1,101)就会生成1~100之间的随机数
  • 运行该代码后就会出现如下结果:

image-20241102114219466

第三部分 比较和隐藏数字

  • 既然是猜数字,就不能让被猜的数字显示出来
  • 注意该代码编译时会报错,无法编译出二进制程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use std::io;
use std::cmp::Ordering;
use rand::Rng;


fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1,101);
println!("The secret number is: {}", secret_number);
println!("Please input your guess.");
let mut guess = String::new();

io::stdin().read_line(&mut guess).expect("Failed to read line");

println!("You guessed: {}",guess);
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}

第三部分解释

  • use std::cmp::Ordering,该段代码从标准库引入了std::cmp::Ordering的类型。Ordering也是枚举类型,有LessGreaterEqual3个变体,用于表示比较数字后的结果

  • match guess.cmp(&secret_number)

    • guess.cmpcmp方法,该方法接收secret_number的引用,然后返回secret_numberguess比较后的结果。返回的结果就是Ordering枚举类型
    • match表达式就用来匹配返回的结果,从而决定下一步应该执行什么代码
      • 假设我们要猜的数是38,而我们猜50,比较返回的结果就是Ordering::Greater变体。
      • match就会去按顺序匹配对应变体,先匹配Ordering::Less,不是该变体就不执行println!("Too small!")
      • 然后就会接下去匹配Ordering::Greater变体,匹配成功就执行println!("Too big!"),执行完后就退出匹配了
  • 如果要隐藏代码就直接注释掉println!("The secret number is: {}", secret_number);,在该段代码的前面添加//

  • 尝试编译第三部分代码,发现我们有一处错误,就是secret_number是整型,而guess是字符串对象,他们无法比较

image-20241102121108704

第四部分 类型转换

  • rust有一个静态强类型系统,同时还有自动进行类型推导的能力。
  • 当我们使用let guess = String::new()时,rust会自动将变量推导为String
  • secret_number可能是i32(32位整数)、u32(32位无符号整数)、i64(64位整数),rust会默认将secret_number视作i32
  • 但是i32String无法直接对比,所以编译器会报错
  • 所以为了正常比较,应该将guess转成u32
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
use std::io;
use std::cmp::Ordering;
use rand::Rng;


fn main() {

println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1,101);

println!("The secret number is: {}", secret_number);
println!("Please input your guess.");
let mut guess = String::new();

io::stdin().read_line(&mut guess).expect("Failed to read line");
let guess: u32 = guess.trim().parse().expect("Please type a number!");


println!("You guessed: {}",guess);
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}

第四部分解释

  • let guess: u32 = guess.trim().parse().expect("Please type a number!");

    • 这边我们又定义了一个guess变量,rust允许定义相同变量名的变量,该变量会覆盖之前的变量,达到隐藏原变量的效果(虽然这种操作有点像弱类型语言的操作,但是rust是强类型语言)。
    • .trim()方法用来去掉首尾空字符,返回处理后的字符串实例(该方法用来去除字符串末尾的\n),使用read_line会读取输入结束的换行符
    • parse方法将当前字符串解析成数值,let guess: u32显示声明要转换为32位无符号整数,变量后面加个:和再跟着要转换的数据类型
    • 由于rust有自动进行类型推导的能力,当我们转换guessu32时,guess会和secret_number比较,所以secret_number也会被自动推导为u32
    • parse方法非常容易出错,这时就要使用expect来进行异常处理
  • 我们再次cargo run 一下程序,发现成功运行了

image-20241102125644821

第五部分 循环

  • rust中,loop关键字会创建一个无限循环,加入程序代码中即可
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
26
27
use std::io;
use std::cmp::Ordering;
use rand::Rng;


fn main() {

println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1,101);

println!("The secret number is: {}", secret_number);
loop{
println!("Please input your guess.");
let mut guess = String::new();

io::stdin().read_line(&mut guess).expect("Failed to read line");
let guess: u32 = guess.trim().parse().expect("Please type a number!");


println!("You guessed: {}",guess);
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
}
  • 编译运行后就可以进行了,但是会出现不想玩时无法正常退出游戏,或者是在猜测成功后无法正常退出

image-20241102130146299

  • 这时我们就要添加一个break的语句,从而在猜对后退出循环
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
26
27
28
29
use std::cmp::Ordering;
use rand::Rng;


fn main() {

println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1,101);

println!("The secret number is: {}", secret_number);
loop{
println!("Please input your guess.");
let mut guess = String::new();

io::stdin().read_line(&mut guess).expect("Failed to read line");
let guess: u32 = guess.trim().parse().expect("Please type a number!");


println!("You guessed: {}",guess);
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
  • 继续编译运行一下,这样猜对后就可以正常退出了

image-20241102130608632

第六部分 异常处理输入

  • 当我们在输入的时候输入了非数字,而是输入了字母就会导致程序异常退出,非常不好
  • 这时我们就要对parse()方法的返回值做处理,这里使用match进行处理,而不使用expect进行异常处理
  • 这种处理是根据parse()返回值这个Result的枚举进行匹配,这里Err(_)_是一个通配符,表示匹配所有的Err()
  • continue语句会使得程序跳转到下一次循环
  • 最后再删除println!("The secret number is: {}", secret_number);即可得到完整代码
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
26
27
28
29
30
31
use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {

println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1,101);

loop{
println!("Please input your guess.");
let mut guess = String::new();

io::stdin().read_line(&mut guess).expect("Failed to read line");
let guess: u32 = match guess.trim().parse(){
Ok(num) => num,
Err(_) => continue,
};


println!("You guessed: {}",guess);
match guess.cmp(&secret_number){
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
  • 使用cargo run编译运行一下就可以开始玩游戏了

image-20241102144243443

Cargo的使用(全)

  • 之前的Cargo命令是简单使用,为了就是快速入门Cargo然后,较快的上手rust,现在就归纳一下cargo的常用命令,Cargo虽然学习编程可能不怎么能体现他的重要性,但是在编写项目的便可以体现出cargo的优势

cargo new

  • 使用cargo启动新项目
1
2
3
4
5
6
7
cargo new 项目名 --bin   //创建一个可执行程序
cargo new hello_world --bin

cargo new 项目名 //编写一个可以被其他项目引用的库和包
cargo new hello_world

# 这两个命令其实没差,生成的效果都一样
  • 使用cargo new hello_world --bin,创建一个可执行程序它的目录如下
    • 其中Cargo.toml,是由Cargo生成的配置文件,用于定义项目的元数据、依赖性、编译配置等。
    • src:里面存放的是源代码,src里面会生成一个main.rs文件,.rs后缀的文件就是rust的源代码文件
1
2
3
4
hello_world
--Cargo.toml(文件)
--src(目录)
--main.rs
  • 接下来查看一些cargo.toml文件里面的具体信息,使用vim cargo.toml命令查看该文件里面的内容
    • name:表示包的名字
    • version:项目版本号
    • edition :Rust的版本
1
2
3
4
5
6
7
8
[package]
name = "hello_world1"
version = "0.1.0"
edition = "2021"

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

[dependencies]

注意:使用cargo new hello_wold命令生成的项目,目录也是与上方一样

cargo build

  • cargo build命令是编译使用cargo new所创建的项目
1
cargon build
  • 直接在所创建的项目内使用cargo build命令编译即可
1
2
3
4
5
myheart@aaa ~/c/r/hello_world1 (master)> ls
Cargo.toml src
myheart@aaa ~/c/r/hello_world1 (master)> cargo build
Compiling hello_world1 v0.1.0 (/home/myheart/code/rust/hello_world1)
Finished dev [unoptimized + debuginfo] target(s) in 0.92s
  • 使用cargo build命令后,项目的目录结构会发生改变,编译后基本上就是这样的目录,具体的了解即可。重点就是为可执行二进制文件
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
26
27
28
hello_world
--Cargo.lock(文件)
--Cargo.toml(文件)
--src(目录)
--main.rs(源代码)
--target(目录)
--CACHEDIR.TAG(文件)
--debug(目录)
--build(目录)
--deps(目录)
--hello_world-65c478c245451323
--hello_world-65c478c245451323.d
--examples(目录)
--hello_world(可执行二进制文件)
--hello_world.d(文件)
--incremental(目录)
--hello_world-2raufob2y547t(目录)
--s-h1czdyejl1-16wthvs-37ja4u7549aastc5b8qe1nrmn(目录)
--24qepgxx259x3ntg.o
--4hcybahg0o19qhm4.o
--2i7b77ao4v5unib8.o
--540zf6nxv88tkrze.o
--3ohs3puklkwxl3d3.o
--c4bpplywo62iusm.o
--dep-graph.bin
--query-cache.bin
--work-products.bin
--s-h1czdyejl1-16wthvs.lock(文件)

cargo run

  • cargo命令就是编译并运行该rust程序,这里我们先使用cargo new hello_world2

image-20241031185004221

  • 然后使用然后我们使用cd命令,进入hello_world2这个目录
  • 再输入cargo run这个命令,即可编译并运行该cargo这个文件
1
2
3
4
5
6
myheart@aaa ~/c/r/hello_world2 (master)> cargo run
Compiling hello_world2 v0.1.0 (/home/myheart/code/rust/hello_world2)
Finished dev [unoptimized + debuginfo] target(s) in 0.62s
Running `target/debug/hello_world2`
Hello, world!
myheart@aaa ~/c/r/hello_world2 (master)>

导入包

  • 当我们要引入外部包或者库的时候我们就要使用cargo这个包管理器
  • 我们先使用cargo new创建了一个新的项目,然后再Cargo.toml这边导入包
  • 导入包后马上执行cargo build,这样就可以导入包了。cargo会先在本地寻找相关包,如果没有相关的包就会远程下载该包,然后放入本地中。
  • 之后的项目如果再使用该包就会在本地中导入,无需再次下载