Rust基础学习-ModulesPackage

在Rust中,模块有助于将程序分割成逻辑单元,以提高可读性和组织性。一旦程序变得更大,将其拆分为多个文件或命名空间非常重要。

模块有助于构建我们的程序。模块是项目的集合:包括函数、结构体甚至其他模块。

cargo


Module

定义模块

Rust中,可以使用mod关键字来定义一个模块,语法如下:

mod module_name {
  // code
}

这里,module_name 是模块的名称。看下面的例子;

mod config {
    fn print() {
        println!("config!");
    }
}

上面的示例中,我们使用mod定义了以config为名称的一个模块。在模块内部,我们定义 了一个简单的函数print;


Rust 模块内项目的可见性

模块中的项目可以是私有的或公共的。默认情况下,模块是私有的。

这意味着模块内部的项目无法在模块外部访问。pub 关键字可用于使项目具有公共可见性。让我们看一个示例。

mod config {
    // items in modules by default have private visibility
    fn select() {
        println!("called config::select");
    }

    // use the `pub` keyword to override private visibility
    pub fn print() {
        println!("called config::print");
    }
}

在这里,我们定义一个名为config的模块,其中包含两个函数select()print()

print()函数以pub关键字开头,这意味着它具有公共可见性。但select()函数则没有。

如果你此时运行程序会发现有一些警告,这是因为我们并没有调用这些函数,现在,我们尝试调用一下;

mod config {
    // items in modules by default have private visibility
    fn select() {
        println!("called config::select");
    }

    // use the `pub` keyword to override private visibility
    pub fn print() {
        println!("called config::print");
    }
}

fn main() {
    // public items inside module can be accessed outside the parent module
    // call public print function from display module
    config::print();
}

在这里,我们使用config::print()语法来调用 config 模块内的公共函数 print():: 运算符用于分隔模块名称和要在模块内调用的项目。

但是,模块内部的私有项目不可在模块外部访问。如果我们尝试在 config 模块内调用私有函数 select(),将会收到编译错误。


注意:当在模块内部某个用pub修饰的方法调用模块内部非pub方法时,我们在调用该pub方法时,其涉及到的非pub方法也将具有pub性质;

我们看个例子:

mod player {
    // private function
    fn focus() {
        println!("called player::focus");
    }

    // public function
    pub fn shift() {
        println!("called player::shift");
    }

    // public function
    pub fn jump() {
        // call private function focus and shift inside the module
        focus();
        shift();
        println!("called player::jump");
    }
}

fn main() {
    // call public function jump from player module
    player::jump();
}

called player::focus
called player::shift
called player::jump

在这里,我们在player模块内定义了多个函数。请注意,我们能够在同一模块内的另一个函数jump()中调用私有函数focus()


模块嵌套

一个模块中还可以在定义其他模块,这就是模块的嵌套;看例子:

// nested module
pub mod player {
    pub mod sprite {
        pub fn create() {
            println!("called player::sprite::create");
        }
    }
}

fn main() {
    // call public function create from sprite module which is inside player module 
    player::sprite::create();
}

输出:

called player::sprite::create

在这里,我们将一个 sprite 模块嵌套在 player 模块内部。我们在 sprite 模块内定义了一个名为 create() 的公共函数,在 main() 函数中通过 player::sprite::create() 调用。


use关键字

我们可以使用use关键字将模块内的项目引入当前作用域。use关键字帮助我们消除调用函数时写出完整模块路径的需要。让我们通过使用use关键字来重新编写我们的嵌套模块示例。

// nested module
pub mod player {
    pub mod sprite {
        pub fn create() {
            println!("called player::sprite::create");
        }
    }
}

// bring the create function into scope
use player::sprite::create;

fn main() {
    // call public function directly
    create();
}

这里,我们使用 use 关键字从 player 模块内部的 sprite 模块中将 create() 函数引入当前作用域。

这样我们可以直接调用 create() 函数,而不需要完全限定名称为 player::sprite::create()。


Crate和Package

一个 crate 可以包含一个或多个 Rust 模块,这些模块可以包含诸如函数、类型和常量之类的代码。

一个 crate 有两种类型:二进制 crate 和库 crate。二进制 crate 是一个 Rust 程序,编译成一个可执行文件或多个可执行文件,并且每个可执行文件都有一个 main() 函数。

crate 不会编译成可执行文件,也没有 main() 函数。库 crate 通常定义了可以在多个项目中使用的共享功能。Crates 可以捆绑在一起形成一个 package


可以使用内置在Rust中的Cargo软件包管理器来创建软件包。 Cargo与Rust一起预安装。我们可以使用 cargo 来创建一个软件包。一个软件包包含一个或多个提供一组功能的crate。

一个包中可以包含许多二进制 crate,但最多只能包含一个库 crate。


创建二进制包

要创建一个二进制包,我们可以在终端中使用 cargo 命令。

$ cargo new hello_world --bin

我们使用 cargo --bin选项创建一个二进制包 hello_world。 这是 cargo 的默认行为。 让我们来看看 hello_world 包的内容。

hello_world
├── Cargo.toml
└── src
    └── main.rs
  • hello_world 是包目录
  • Cargo.toml 是一个包含有关 crate 的元数据的文件,如其名称、版本和依赖项
  • src/main.rs crate 根目录,包含二进制包的源代码

创建库包

$ cargo new hello_world_lib --lib

包结构如下:

hello_world_lib
├── Cargo.toml
└── src
    └── lib.rs
  • hello_world_lib 是包目录
  • Cargo.toml 是一个包含有关包的元数据的文件,例如其名称、版本和依赖关系
  • src/lib.rs 是 crate 根目录,包含库包的源代码

一个包可以包含src/main.rssrc/lib.rs。在这种情况下,它有两个 crate:一个二进制 crate 和一个库 crate,两者都与包的名称相同。例如,

hello_world
├── Cargo.toml
└── src
    └── lib.rs
    └── main.rs

Cargo包管理器

Cargo

CargoRust的包管理器。它与Rust一起预装,并可用于打包依赖项,管理它们以及构建和分发我们自己的包/库。

cargo的特点:

  • 依赖管理

Cargo 可轻松管理我们项目的依赖项,包括添加、更新和删除依赖项。
构建和打包

Cargo 可自动构建和打包我们的 Rust 项目,创建可与他人共享的二进制或库代码。

  • 文档生成

Cargo 可自动为我们的代码生成文档,使其他开发人员更容易理解和使用我们的库。

  • 下载 crate

Cargo 可从 crates.io 下载并安装库,这是 Rust crate 的中央存储库。

  • 运行二进制或测试

Cargo 可构建我们的源代码,运行可执行二进制文件,并运行我们的测试。


依赖管理

Cargo 的主要功能之一是可以下载、管理外部库。让我们看看如何从 crates.io 使用外部 crate 的示例。crates.io 是一个中央仓库,我们可以从中获取和发布用于 Rust 的共享库。

  • 创建一个项目
$ cargo new hello_world
  • 添加一个生成随机数的依赖rand,我们可以在cargo.toml中的[dependencies]部分进行添加
name = "hello_world"
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.8.5"

我们还可以使用命令 cargo add rand 来为我们的项目添加依赖。

注意,如果通过命令的方式添加依赖,在添加时Rust就会加载编译该依赖,而通过cargo.toml手动添加时,程序会在你首次运行程序时进行加载编译的操作。

  • 使用依赖
use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();

    // simulate rolling a die
    println!("roll = {}", rng.gen_range(1..=6));
}

# Output: roll = 5

构建和执行

Rust支持使用cargo命令对程序进行buildrun.命令分别是

  • cargo build
  • cargo run

一般情况下,执行cargo run时,默认会自动执行cargo build,所以一般我们需要运行程序时不需要先执行build,再执行run,而是直接执行cargo run即可。

常用命令一览表:

CommandDescription
cargo newCreate a new Rust project with basic directory structure
cargo buildBuild (compile) the current project and generate a binary executable
cargo runBuild and run your current project (cargo build + run)
cargo checkBuild the current project without generating a binary executable
cargo addAdd a new dependency and include it in Cargo.toml file
cargo updateUpdate all dependencies of current project to latest version

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/704420.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

手撕设计模式——计划生育之单例模式

1.业务需求 ​ 大家好,我是菠菜啊。80、90后还记得计划生育这个国策吗?估计同龄的小伙伴们,小时候常常被”只生一个好“”少生、优生“等宣传标语洗脑,如今国家已经放开并鼓励生育了。话说回来,现实生活中有计划生育&…

SqlSugar使用DbFirst对象根据数据库表结构创建实体类-C#

本文所述开发环境:.C#、NET8、Visual Studio2022 1. 在项目中安装SqlSugar 在Visual Studio2022中新建一个 C# 的控制台应用程序,框架选择 .Net8。新建后如下图所示: 然后打开NuGet程序包管理器 搜索 SqlSugarCore 并安装 安装后在解决方案…

资源分享—2021版市级制图规范符号库

汇总整理超图平台软件相关的各类资源(包括但不限于符号库、地图模板、地理处理模型等),助力项目的高效制图、提高数据生产效率等业务。 本次分享新版国土空间规划【2021版市级制图规范符号库】,提供SuperMap格式符号库下载。 1.市…

数据结构的队列,链表,栈的基础操作

1&#xff1a;队列 #include <stdio.h>#include <stdlib.h>#include "./02队列.h"/** function: 创建一个空的队列* param [ in] * param [out] * return */Sequeue* xinduilie(){Sequeue* sq (Sequeue*)malloc(sizeof(Sequeue)); if(N…

Java 反射机制 -- Java 语言反射的概述、核心类与高级应用

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 010 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自…

镜像拉取失败:[ERROR] Failed to pull docker image

问题描述 执行 bash docker/scripts/dev_start.sh 命令提示错误&#xff1a; permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post “http://%2Fvar%2Frun%2Fdocker.sock/v1.45/images/create?fromImageregistry.b…

在Lua解释器中注册自定义函数

本文目录 1、引言2、函数注册2.1注册原理 2.2 注册函数 3、实操3.1 编写注册函数3.2编写测试代码 4、结论 文章对应视频教程&#xff1a; 暂无&#xff0c;可以关注我的B站账号等待更新。 点击图片或链接访问我的B站主页~~~ 1、引言 在之前的博客中&#xff0c;已经介绍了如何…

JAVA小知识17:数组,从0基础到掌握

数组&#xff0c;无论在哪种编程语言当中都是最基础&#xff0c;最广泛使用的一种线性表数据结构&#xff0c;这篇文章将从多个角度来从浅入深的讲述数组。 本文讲述了数组的概念&#xff0c;定义&#xff0c;初始化方法以及如何遍历数组&#xff0c;如何赋值&#xff0c;关于数…

4. Revit API UI 之 Ribbon(界面)

4. Revit API UI 之 Ribbon&#xff08;界面&#xff09; 第二篇中&#xff0c;我们提到了IExternalApplication&#xff0c;该接口需要实现两个方法&#xff1a;Revit启动时调用的OnStartup 方法&#xff0c;和Revit关闭时调研的OnShutdown 方法。文中还给了个例子&#xff0…

剧透!「飞凌嵌入式技术创新日」3大亮点抢先看

6月25日&#xff0c;飞凌嵌入式技术创新日&#xff08;北京站&#xff09;即将开幕&#xff0c;一场嵌入式前沿科技的高端局就在眼前。 飞凌嵌入式作为国内较早专业从事嵌入式技术的企业&#xff0c;凭借18年的行业深耕和丰富的技术积累&#xff0c;已在业界赢得了广泛的影响力…

LabVIEW电源适应能力检测系统

随着工业自动化程度的提高&#xff0c;电源质量直接影响设备的稳定运行。利用LabVIEW开发一个单相电源适应能力检测系统&#xff0c;该系统通过智能化和自动化测试&#xff0c;提高了测试效率&#xff0c;减少了人为错误&#xff0c;保证了电源质量的可靠性。 项目背景 在现代…

大厂面试必备:如何轻松实现分布式Session管理?

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!​​​​​​​ 大家好,我是小米,一个29岁的技术爱好者,喜欢分享各种技术干货。今天我们来聊一聊阿里巴巴面试中的一个经典问题:如何实现分布式Sess…

HCIA12 NAT网络地址转换实验

NAT&#xff08;Network Address Translation&#xff09;是将 IP 报头中的 IP 地址转换为另一个 IP 地址的过程。主要俩好处&#xff1a; • 有效避免来自外网的攻击&#xff0c;可以很大程度上提高网络安全性。 • 控制内网主机访问外网&#xff0c;同时也可以控制外网…

你的医书是假的!批评《DDD诊所——聚合过大综合症》(合集)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 &#xff08;《你的医书是假的&#xff01;》原文写于2023年8月&#xff0c;以系列文章方式发表&#xff0c;现合并成一篇文章&#xff09; 一、说在前面 这两天在“ Thoughtworks洞见…

Mac vscode could not import github.com/gin-gonic/gin

问题背景&#xff1a; 第一次导入一个go的项目就报红 问题分析&#xff1a; 其实就是之前没有下载和导入gin这个web框架包 gin是一个golang的微框架&#xff0c;封装比较优雅&#xff0c;API友好&#xff0c;源码注释比较明确。 问题解决&#xff1a; 依次输入以下命令。通…

【STM32】输入捕获应用-测量脉宽或者频率(方法1)

图1 脉宽/频率测量示意图 1 测量频率 当捕获通道TIx 上出现上升沿时&#xff0c;发生第一次捕获&#xff0c;计数器CNT 的值会被锁存到捕获寄存器CCR中&#xff0c;而且还会进入捕获中断&#xff0c;在中断服务程序中记录一次捕获&#xff08;可以用一个标志变量来记录&#…

阿里最强开源大模型本地部署、API调用和WebUI对话机器人

阿里巴巴通义千问团队发布了Qwen2系列开源模型&#xff0c;该系列模型包括5个尺寸的预训练和指令微调模型&#xff1a;Qwen2-0.5B、Qwen2-1.5B、Qwen2-7B、Qwen2-57B-A14B以及Qwen2-72B。对比当前最优的开源模型&#xff0c;Qwen2-72B在包括自然语言理解、知识、代码、数学及多…

新加坡裸机云多IP服务器为何适合跨境外贸业务

新加坡裸机云多IP服务器在跨境外贸业务中展现出了卓越的适配性&#xff0c;其独特优势为外贸企业提供了强大的支持。以下将详细阐述为何新加坡裸机云多IP服务器是跨境外贸业务的理想选择。 首先&#xff0c;新加坡裸机云多IP服务器在性能上表现出色。由于去除了虚拟化层的开销&…

聚观早报 | 粉笔将推AI智能老师;比亚迪宋L DM-i车型官宣

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 6月13日消息 粉笔将推AI智能老师 比亚迪宋L DM-i车型官宣 真我GT7 Pro配置全面升级 理想发布最新单周销量榜单 …

如何免费用 Qwen2 辅助你翻译与数据分析?

对于学生用户来说&#xff0c;这可是个好消息。 开源 从前人们有一种刻板印象——大语言模型里好用的&#xff0c;基本上都是闭源模型。而前些日子&#xff0c;Meta推出了Llama3后&#xff0c;你可能已经从中感受到现在开源模型日益增长的威力。当时我也写了几篇文章来介绍这个…