✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Rust开发,Python全栈,Golang开发,云原生开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:Rust语言通关之路
景天的主页:景天科技苑
文章目录
1、名词定义
包:Cargo的一个功能,允许构建,测试,和分享crate。
crate:一个模块的树形结构,形成库或二进制项目。
模块:通过use来使用,用来控制作用域和路径的私有性。
路径:一个命名 例如结构体、函数或模块等项的方式
在 Rust 中,模块(module)是组织代码的基础单位,它帮助你将代码划分为多个逻辑部分,便于管理、复用和控制访问权限。
模块是一个命名空间,用于组织函数、结构体、枚举、常量、trait 和其他模块。Rust 中的模块可以嵌套,并且支持私有和公开访问控制。
2、包和crate
(1) crate root 是一个源文件,Rust 编译器以它为起始点,并构成你的 crate 的根模块。
(2) 包提供一系列功能的一个或多个Crate。
(3) Crate root是src/main.rs或者是src/lib.rs。说明: 如果只有main.rs则说明这个包只有一个crate(main),如果同时拥有main.rs和其它的lib.rs(不一定是这个名字)则说明拥有多个crate。
(4) crate会将一个作用域的相关功能分组到一起,使得该功能可以很方便的在多个项目之间共享。
3、Rust模块
3.1 模块的定义与作用
模块(Module)是Rust中代码组织的基本单元,主要功能包括:
命名空间管理:防止命名冲突
封装性:通过pub关键字控制可见性
代码组织:将相关功能逻辑分组
编译单元:影响编译过程和代码生成
3.2 基本语法
在Rust中,使用mod关键字定义模块:
mod my_module {
// 模块内容
}
模块可以包含函数、结构体、枚举、trait、其他模块等。
3.3 模块的可见性
Rust默认所有项(item)都是私有的,只在当前模块内可见。使用pub关键字可以使其对外可见:
mod my_module {
pub fn public_function() {
println!("This is public");
}
fn private_function() {
println!("This is private");
}
}
3.4 模块的多种定义方式
3.4.1 内联模块
直接在文件中使用mod关键字定义:
//定义模块
mod factory {
//如果对外暴露模块,都得使用pub
pub mod prduct_car {
pub fn new_car() {
println!("new car");
}
}
pub mod product_bike {
pub fn new_bike() {
println!("new bike");
}
}
}
fn main() {
//使用模块
factory::prduct_car::new_car();
factory::product_bike::new_bike();
}
3.4.2 文件模块
更常见的做法是将模块放在单独的文件中。
方式一:添加模块文件
直接在项目src下,创建个rs文件network.rs
pub fn connect() {
println!("connect");
}
pub fn disconnect() {
println!("disconnect");
}
pub fn send() {
println!("send");
}
pub fn receive() {
println!("receive");
}
直接在main.rs中使用mod引用
mod network;
fn main() {
network::connect();
network::send();
network::receive();
network::disconnect();
}
方式二:添加库
我们在cargo创建的项目目录下,通过cargo new --lib mylib 创建一个库
我们创建的库里面的lib.rs文件中有测试模块
在我们创建的库mylib的src下创建个文件模块factory.rs,将之前通过内联模式创建的模块代码拿过来
在lib.rs中导出我们创建的模块
//在lib.rs中导出我们创建的模块
pub mod factory;
然后,在我们得项目的Cargo.toml文件中,将我们创建的库的路径指定
在[dependencies]下面添加
main.rs中导入我们创建的库,并使用
3.4.3 目录模块
对于更复杂的模块,可以使用目录形式。例如,创建一个client模块:
src/
├── client/
│ ├── mod.rs
│ ├── http.rs
│ └── tcp.rs
├── main.rs
http.rs
tcp.rs
mod.rs是目录模块的入口文件:
导出模块http和tcp
// client/mod.rs
pub mod http;
pub mod tcp;
然后在main.rs中使用
mod client;
fn main() {
//注意,在http.rs中导出模块名http,在mod.rs中又导出http模块名,所以相当于又两层http模块名
client::http::http::get();
client::tcp::tcp::connect();
}
3.5 模块路径与use关键字
3.5.1 绝对路径与相对路径
Rust中有两种引用模块项的路径:
绝对路径:从crate根开始,使用crate::或外部crate名称
相对路径:从当前模块开始,使用self::、super::或直接使用标识符
mod client {
pub mod http {
pub fn connect() {}
}
}
// 绝对路径
crate::client::http::connect();
// 相对路径
client::http::connect();
3.5.2 use关键字
use关键字用于将路径引入作用域,简化代码:
use client::http;
http::connect();
可以使用as创建别名:
use std::io::Result as IoResult;
起别名
高级用法:
// 嵌套路径
use std::{cmp::Ordering, io};
// 引入多个项
use std::collections::{HashMap, HashSet};
// 引入所有公共项(谨慎使用)
use std::collections::*;
3.6 重导出
重导出允许你公开模块内部的项,并为其提供新的路径:
// src/lib.rs
mod internal {
pub mod network {
pub fn connect() {}
}
}
pub use internal::network::connect;
现在用户可以直接使用crate::connect()而不是crate::internal::network::connect()。
3.7 访问控制与可见性
3.7.1 可见性修饰符
Rust提供了精细的可见性控制:
pub - 完全公开
pub(crate) - 当前crate内可见
pub(super) - 父模块中可见
pub(in path) - 指定路径中可见
示例:
mod outer {
pub mod inner {
pub(in crate::outer) fn restricted() {}
pub fn example() {
restricted(); // 可以访问
}
}
pub fn test() {
inner::restricted(); // 可以访问
}
}
fn main() {
outer::inner::example();
// outer::inner::restricted(); // 错误:不可见
}
3.7.2 结构体与枚举的可见性
结构体字段需要单独控制可见性:
使用内联模块来创建结构体
//内联模块
mod mystruct {
#[derive(Debug)]
pub struct MyStruct {
pub username: String,
pub age: i32,
money: i32, //私有字段
}
//实现MyStruct的构造函数和方法
impl MyStruct {
//构造函数,其实就是一个关联函数
pub fn new(username: String, age: i32) -> MyStruct {
MyStruct { username, age, money: 9999990 }
}
//方法
//方法的第一个参数是&self,表示调用该方法的实例
pub fn display(&self) {
println!("username: {}, age: {}, money: {}", self.username, self.age, self.money);
}
}
}
//使用模块
use mystruct::MyStruct;
fn main() {
let mystruct = MyStruct::new("jingtian".to_string(), 18);
mystruct.display();
}
公有字段可以访问,私有字段不能访问
枚举的变体继承枚举的可见性:
pub enum HttpStatus {
Ok, // 公开
NotFound, // 公开
ServerError, // 公开
}
3.7.3 通过super访问父级模块
//内联模块
mod mystruct {
pub mod mod_b {
pub fn display() {
println!("hello, B");
}
//子模块
pub mod mod_c {
pub fn print_c() {
println!("hello, C");
//子模块访问父模块方法
super::display();
}
}
}
}
//使用模块
// use mystruct::MyStruct;
use mystruct::mod_b;
fn main() {
//子模块访问父模块方法
mod_b::mod_c::print_c();
}
子模块mod_c中的print_c方法,调用了父模块mod_b的print_b方法。
因此也打印了 hello, B
4、第三方库管理
上面都是我们自己写的库,如果我们使用别人写好的库该怎么使用呢?比如加密库等
Rust语言的库的官方网站crate,可以登录这个网站查找你想要的第三方库
https://crates.io/
需要修改Cargo.toml文件,来实现加载第三方库
比如我们需要rand库
直接搜索
直接复制这个版本到Cargo.toml文件的dependencies下面
放到dependencies下面,保存后就会自动加载依赖
但是不推荐直接这种方式安装第三方库
我们使用cargo-edit这个插件
安装
cargo install cargo-edit
添加库
cargo add dependency_name //最新版
#安装指定版本
cargo add dependency_name@1.2.3
#添加开发时用的依赖库
cargo add --dev dev dependency_name
#添加构建时用的依赖库
cargo add --build build dependency_name
#删除库
cargo rm dependency_name
#删除dev的库
cargo rm --dev dependency_name
#删除build的库
cargo rm --build dependency_name
设置国内源
推荐使用https://rsproxy.cn/。这个库比较全,速度也比较快
Linux和Mac修改 ~/.cargo/config
[source.crates-io]
replace-with = 'rsproxy-sparse'
[source.rsproxy]
registry = "https://rsproxy.cn/crates.io-index"
[source.rsproxy-sparse]
registry = "sparse+https://rsproxy.cn/index/"
[registries.rsproxy]
index = "https://rsproxy.cn/crates.io-index"
[net]
git-fetch-with-cli = true
Windows设置国内源:
安装方式不同
windows可选Rust 的目标平台标识
x86 64-pc-windows-msvc //可以通过rustup show查看自己安装的版本
x86_64-pc-windows-gnu(不推荐)
rustup component
某些组件可能不同
设置国内源的文件路径不同,将上述文件配置到下方config即可
C:\Users<你的用户名>.cargo\config
第三方库使用案例:
我们使用加密库rust-crypto
先登录 https://crate.io
查找该库
通过cargo add来安装
cargo add rust-crypto
安装完之后,会在Cargo.toml文件中的dependencies中自动生成依赖和版本。我们就可以使用了
使用第三方库
//extern crate是edition 2018之前的用法
extern crate crypto; //edition 2018以及之后的版本不用加这个
use crypto::digest::Digest;
use crypto::sha3::Sha3;
fn main() {
//使用第三方库
let mut hasher = Sha3::sha3_256();
hasher.input(b"hello world");
let result = hasher.result_str();
println!("SHA3-256 hash: {}", result);
}
edition 2018以及之后的版本用法