前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Rust中使用模块组织代码

Rust中使用模块组织代码

作者头像
端碗吹水
发布于 2022-06-01 01:08:41
发布于 2022-06-01 01:08:41
61800
代码可运行
举报
运行总次数:0
代码可运行

[TOC]


Rust中的模块化编程

自上个世纪 90 年代以来,软件工程的复杂性越来越高,程序渐渐从一个人的独狼开发转为多人团队协作开发。在今天,通过 Github 或中心化的代码分发网站,我们可以轻松的在一个软件工程中同时引入世界各地的开发者开发的代码,我们与同事在同一个工程目录下并行开发不同的程序功能,或者在不拷贝代码的前提下将一个工程中的代码在另一个工程中复用。这一切都是因为模块化编程。

模块化编程,是强调将计算机程序的功能分离成独立的和可相互改变的“模块”的软件设计技术,它使得每个模块都包含着执行预期功能的一个唯一方面所必需的所有东西,复杂的系统被分割为小块的独立代码块。

Rust 项目的代码组织包含以下三个基本概念:

  • Package(包)
  • Crate(箱)
  • Module(模块)

Package

Package 用于管理一个或多个 Crate。创建一个 Package 的方式是使用 cargo new,我们来看看一个 Package 包含哪些文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ cargo new my-project
     Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs

当我们输入命令时,Cargo 创建了一个目录以及一个 Cargo.toml 文件,这就是一个 Package。默认情况下,src/main.rs 是与 Package 同名的二进制 Crate 的入口文件,因此我们可以说我们现在有一个 my-project Package 以及一个二进制 my-project Crate。同样,如果在创建 Package 的时候带上 --lib,那么 src/lib.rs 将是它的 Crate 入口文件,且它是一个库 Crate。

如果我们的 src 目录中同时包含 main.rslib.rs,那么我们将在这个 Package 中同时得到一个二进制 Crate 和一个库 Crate,这在开发一些基础库时非常有用,例如你使用 Rust 中实现了一个 MD5 函数,你既希望这个 MD5 函数能作为库被别人引用,又希望你能获得一个可以进行 MD5 计算的命令行工具:那就同时添加 main.rslib.rs 吧!

Crate

Crate 是 Rust 的最小编译单元,即 Rust 编译器是以 Crate 为最小单元进行编译的。Crate 在一个范围内将相关的功能组合在一起,并最终通过编译生成一个二进制或库文件。例如,我们在上一章中实现的猜数字游戏就使用了 rand 依赖,这个 rand 就是一个 Crate,并且是一个库的 Crate。

Module

Module 允许我们将一个 Crate 中的代码组织成独立的代码块,以便于增强可读性和代码复用。同时,Module 还控制代码的可见性,即将代码分为公开代码和私有代码。公开代码可以在项目外被使用,私有代码则只有项目内部的代码才可以访问。定义一个模块最基本的方式是使用 mod 关键字:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mod mod1 {
     pub mod mod2 {
          pub const MESSAGE: &str = "Hello World!"
          // ...
     }
     // ...
}

fn main() {
     println!(mod1::mod2::MESSAGE);
}

使用pub改变可见性

Rust 中模块内部的代码,结构体,函数等类型默认是私有的,但是可以通过 pub 关键字来改变它们的可见性。通过选择性的对外可见来隐藏模块内部的实现细节。

比较常用的三种 pub 写法:

  • pub:成员对模块可见
  • pub(self):成员对模块内的子模块可见
  • pub(crate):成员对整个 crate 可见

如果不使用 pub 声明,成员默认的可见性是私有的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mod mod1 {
    pub const MESSAGE: &str = "Hello World!";
    const NUMBER: u32 = 42;

    pub(self) fn mod1_pub_self_fn() {
        println!("{}", NUMBER);
    }

    pub(crate) enum CrateEnum {
        Item = 4,
    }

    pub mod mod2 {
        pub const MESSAGE: &str = "Hello World!";

        pub fn mod2_fn() {
            super::mod1_pub_self_fn();
        }
    }
}

fn main() {
    println!("{}", mod1::MESSAGE);
    println!("{}", mod1::mod2::MESSAGE);
    mod1::mod2::mod2_fn();
    println!("{}", mod1::CrateEnum::Item as u32);
}

结构体的可见性

结构体中的字段和方法默认是私有的,通过加上 pub 修饰语可使得结构体中的字段和方法可以在定义结构体的模块之外被访问。要注意,与结构体同一个模块的代码访问结构体中的字段和方法并不要求该字段是可见的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mod mod1 {
    pub struct Person {
        pub name: String,
        nickname: String,
    }

    impl Person {
        pub fn new(name: &str, nickname: &str) -> Self {
            Person {
                name: String::from(name),
                nickname: String::from(nickname),
            }
        }

        pub fn say_nick_name(&self) {
            println!("{}", self.nickname);
        }
    }
}

fn main() {
    let p = mod1::Person::new("jack", "baby");
    println!("{}", p.name);
    // println!("{}", p.nickname); // 不能访问 nickname
    p.say_nick_name();
}

使用use绑定模块成员

正常情况下当我们试图从模块内中访问其成员时,需要输入完整的路径,例如使用 std::fs::read 从磁盘上读取文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn main() {
    let data = std::fs::read("src/main.rs").unwrap();
    println!("{}", String::from_utf8(data).unwrap());
}

可以使用 use 关键词将完整路径绑定到一个新的名称,这可以减少重复代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use std::fs;

fn main() {
    let data = fs::read("src/main.rs").unwrap();
    println!("{}", String::from_utf8(data).unwrap());
}

可以使用 as 关键字将导入绑定到一个其他名称,它通常用在有多个不同模块都定义了相同名字的成员时使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use std::fs as stdfs;

fn main() {
    let data = stdfs::read("src/main.rs").unwrap();
    println!("{}", String::from_utf8(data).unwrap());
}

使用super与self简化模块路径

除了使用完整路径访问模块内的成员,还可以使用 super 与 self 关键字相对路径对模块进行访问:

  • super:上层模块
  • self:当前模块

当上层模块,当前模块或子模块中拥有相同名字的成员时,使用 super 与 self 可以消除访问时的歧义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fn function() {
    println!("function");
}

pub mod mod1 {
    pub fn function() {
        super::function();
    }

    pub mod mod2 {
        fn function() {
            println!("mod1::mod2::function");
        }

        pub fn call() {
            self::function();
        }
    }
}

fn main() {
    mod1::function();
    mod1::mod2::call();
}

项目目录层次结构

将模块映射到文件

使用 mod <路径> 语法,将一个 rust 源码文件作为模块内引入:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
src
├── main.rs
└── mod1.rs

mod1.rs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pub const MESSAGE: &str = "Hello World!";

main.rs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mod mod1;

fn main() {
    println!("{}", mod1::MESSAGE);
}

将模块映射到文件夹

当一个文件夹中包含 mod.rs 文件时,该文件夹可以被作为一个模块:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
src
├── main.rs
└── mod1
    └── mod.rs

mod1/mod.rs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pub const MESSAGE: &str = "Hello World!";

main.rs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mod mod1;

fn main() {
    println!("{}", mod1::MESSAGE);
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JQuery ajax调用asp.net的webMethod
本文章转载:http://www.cnblogs.com/zengxiangzhan/archive/2011/01/16/1936938.html
跟着阿笨一起玩NET
2018/09/19
2.4K0
ASP.Net MVC框架配置与分析
前几年的时候ASP.Net就有MVC的概念,实际上就是我们熟悉的WebForm开发模型。 1、Model层与视图无关,并且只与数据库相关: 伪代码: pulic class Model {       pulic DataSet ds()       {             //数据库库取数据             return ds;       } } 2、Controller实际上就是我们熟悉的Default.aspx.cs文件,继承自System.Web.UI.Page 类的文件 3、Vie
菩提树下的杨过
2018/01/22
1.6K0
ASP.Net MVC框架配置与分析
自定义Unity对象生命周期管理集成ADO.NET Entity Framework
在Unity中,从Unity 取得的实例为 Transient。如果你希望使用多线程方式,就需要在组成时使用lifecycle参数,这时候取出的组件就不再是同一个了。在Unity IOC中,它支持我们对于组件的实例进行控制,也就是说我们可以透明的管理一个组件拥有多少个实例。Unity IOC容器提供了如下几种生命处理方式: # Singleton:一个组件只有一个实例被创建,所有请求的客户使用程序得到的都是同一个实例。 # Transient:这种处理方式与我们平时使用new的效果是一样的,对于每次的请
张善友
2018/01/30
1K0
Jquery ajax调用后台aspx后台文件方法(不是ashx)
在asp.net webForm开发中,用Jquery ajax调用aspx页面的方法常用的有两种:下面我来简单介绍一下。   (1)通过aspx.cs的静态方法+WebMethod进行处理    简单的介绍下WebMethod方法的用法    1.修饰符主要用public static修饰    2.方法前面加上[WebMethod]属性表明这是WebMethod方法    3.前台html页面(Client端)访问时要使用post方法,和后台.cs文件进行数据交互,否则会返回整个html页面。    4
郑小超.
2018/01/24
7.4K0
搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (四)配置全攻略
     本篇目的:配置Spring.Net和Nhibernate。配置Spring.Net来注入Nhibernate需要的SessionFactory,配置业务逻辑层所需要的Dao层属性的支持。配置这套框架与web程序关联。
老马
2022/05/10
1.1K0
搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (四)配置全攻略
ASP.NET 使用Ajax
之前在Ajax初步理解中介绍了对Ajax的初步理解,本文将介绍在ASP.NET中如何方便使用Ajax,第一种当然是使用jQuery的ajax,功能强大而且操作简单方便,第二种是使用.NET封装好的ScriptManager。
全栈程序员站长
2022/09/06
3K0
ASP.NET 使用Ajax
Asp.Net 之 Web.config 配置文件详解
  在asp.net中配置文件名一般默认是web.config。每个web.config文件都是基于XML的文本文件,并且可以保存到Web应用程序中的任何目录中。在发布Web应用程序时web.config文件并不编译进dll文件中。如果将来客户端发生了变化,仅仅需要用记事本打开web.config文件编辑相关设置就可以重新正常使用,非常方便。
CherishTheYouth
2019/09/11
6.2K0
Asp.Net 之 Web.config 配置文件详解
【转】配置子目录Web.config使其消除继承,用虚拟目录创建多个网站的方法
原文链接:http://www.wtnzone.com/post/2011/02/20/Set-Web-Config-to-Turn-Inheritance-Off.aspx
拓荒者IT
2019/09/25
1.8K0
ASP.NET AJAX(10)__Authentication ServiceAuthentication ServiceAuthentication Service属性Authentication
在通常情况下,如果使用AJAX方式调用WebService,则可能被恶意用户利用,造成性能以及安全性的问题,所以我们需要使用一些验证方式来保护WebService,最常见方式就是Forms Authentication,这也是一种用法很简单的方式 一个使用FormsAuthentication保护WebService调用的示例 首先创建一个名为ProtectedService的WebService,代码如下 using System; using System.Collections.Generic; us
小白哥哥
2018/03/07
1.9K0
ASP.NET AJAX(2)__ASP.NET 2.0 AJAX Extensions
ASP.NET 2.0 AJAX Extensions为我们提供的主要功能如下 序列化和反序列化 客户端访问Web Service方法 服务器端AJAX控件 _____ScriptManager _____UpdatePanel _____Extender 微软的ASP.NET AJAX有一点非常让人感觉神奇的一点,也算是他宣传的一个鳌头,说的是,所有的ASP.NET程序员,不用写任何javascript代码就可以实现AJAX,那么UpdatePanel呢,就是说着话的资本,我们也知道,几乎
小白哥哥
2018/03/07
1.7K0
ASP.NET AJAX(4)__客户端访问WebService服务器端释放WebService方法客户端访问WebService客户端访问PageMethod错误处理复杂数据类型使用基础客户端代理的
服务器端释放WebService方法 编写一个普通的WebService 为WebService类添加自定义的属性标记__ScriptServiceAttribute 释放WebService方法                   __访问级别为Public                   __使用WebServiceAttribute进行标记 为页面中的ScriptManager引入asmx文件 客户端访问WebService [Namespaces.]ClassName.MethodName 依次
小白哥哥
2018/03/07
5K0
学习Altas 笔记[JS简单调用服务端方法]
      在Ajax框架中,Asp.net方面最强当属Altas最强,以前使用AjaxPro.Net和MagicAjax. 最几个都比较好用。这几个月来Altas已经进入CTP版本,是开始学习研究Altas的时机了。准备利用Altas为 http://www.yupsky.com 开发成员之间在线通讯的类似于MSN这样的功能。今天初步的学习了一下Altas,最基础的学习内容就是使用javascript调用服务端代码。      Altas和AjaxPro.Net类似,但比AjaxPro.Net强大很多。学
张善友
2018/01/19
9330
学习Altas 笔记[JS简单调用服务端方法]
ASP.NET那点不为人知的事(二)
上一篇博文《ASP.NET那点不为人知的事(一)》中我们提到HttpApplication有19个标准事件,在HttpApplication的第8个事件PostMapRequestHandlerExcute触发的时候,标志着已经获取了处理当前请求的处理程序对象,在第11个事件PreRequestHandlerExcute之后,HttpApplication将执行这个处理程序,接下来我们继续讨论以下话题: HttpContext状态管理 处理HttpApplication的事件 常见的HttpMod
用户1161731
2018/01/11
7490
ASP.NET那点不为人知的事(二)
Asp.Net 用Jquery和一般处理程序实现无刷新上传大文件
上传文件算是比较常规的一个功能,Asp.Net自带了一个上传控件 FileUpload ,简单易用但是体验不太好,所有开发者经常都会选择一个JS插件来进行上传,比如:Uploadify SWFupload  等等... 如果没有特别高的要求,也可以自已实现无刷新有等待效果的上传... 知识了解 利用jQuery Form Plugin的ajaxSubmit方法通过AJAX提交表单    表单提交后,在一般处理程序中HttpContext.Current.Request.Files才能获
Porschev
2018/01/16
2.2K0
Asp.Net 用Jquery和一般处理程序实现无刷新上传大文件
Jquery Ajax 跨域调用asmx类型 WebService范例
摘要:Ajax 在 Web 2.0 时代起着非常重要的作用,然而有时因为同源策略(SOP)(俗称:跨域问题(cross domain)) 它的作用会受到限制。在本文中,将学习如何克服合作限制。本文以asmx方式搭建webservice作为测试用后端,给出完整的前后端调用解决方案、范例代码。
全栈程序员站长
2022/09/06
1.8K0
Jquery Ajax 跨域调用asmx类型 WebService范例
Asp.net利用JQuery弹出层加载数据
最近看QQ空间里面的投票功能很使用。点击一个链接就弹出一个层,然后再加载一些投票信息,旁边的区域变成灰色不可用状态。其实这不算什么高深的技术,只要在ASP.NET中利用JQuery结合一般处理程序ASHX即可搞定了。
SAP梦心
2022/05/10
3.2K0
Asp.net利用JQuery弹出层加载数据
在asp.net mvc上应用新ASP.NET图表控件
微软去年11月发布了一个很酷的新ASP.NET服务器控件,<asp:chart />,可以免费用在ASP.NET 3.5中,而且还可以用在asp.net mvc。可以看新ASP.NET图表控件<asp:chart runat="server"/>。 相关资源的下载链接: Download the free Microsoft Chart Controls Download the VS 2008 Tool Support for the Chart Controls Download the Microso
张善友
2018/01/30
3K0
在asp.net mvc上应用新ASP.NET图表控件
asp.net MVC 应用程序的生命周期
  首先我们知道http是一种无状态的请求,他的生命周期就是从客户端浏览器发出请求开始,到得到响应结束。那么MVC应用程序从发出请求到获得响应,都做了些什么呢?       本文我们会详细讨论MVC应用程序一个请求的生命周期,从一个控件到另一个控件是怎样被处理的。我们还会详细介绍一下整个请求的生命周期中,用到的相关组件。因为在平常的开发过程中,我们可能知道怎样去使用MVC框架来处理相关的请求,大部分的时候我们只是在controller和action方法之间做相关的处理,对于真正内在的运行机制可能不是很了解。
用户1172223
2018/01/26
2K0
jQuery Gallery Plugin在Asp.Net中使用
jQuery Gallery Plugin在Asp.Net中使用 推荐一个简单易用的Gallery插件:jQuery Gallery Plugin 下面是在Asp.Net开发中应用 示例截图: image.png -------------------------------------------------------------------------------风骚分隔线----------------------------------------------------------------
Porschev
2018/01/16
1.3K0
jQuery Gallery Plugin在Asp.Net中使用
ASP.NET AJAX(11)__ScriptManagerUpdatePanel的支持成员功能控制成员脚本控件支持成员ScriptMode和ScriptPathLoadScriptsBeforeU
ScriptManager的作用,这个不言而喻,它是整个的ASP.NET AJAX的核心 UpdatePanel的支持成员 static void RegisterArrayDeclaration static void RegisterClientScriptBlock static void RegisterScriptInclude static void RegisterClientScriptResource static void RegisterExpandoAttribute static
小白哥哥
2018/03/07
9850
推荐阅读
相关推荐
JQuery ajax调用asp.net的webMethod
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验