Rust入门(四):程序结构和异常处理
创始人
2024-05-04 04:55:22
0

Rust程序结构

rust中有多种的模块系统来实现程序的结构,包括

  • Packages)。

  • Crates

  • 模块Modules

Crate

crate 是 Rust 在编译时最小的代码单位。crate 有两种形式:二进制项和库。

  • 二进制项

二进制项可以被编译为可执行程序,比如一个命令行程序或者一个服务器。它们必须有一个 main 函数来定义当程序被执行的时候所需要做的事情。

库并没有 main 函数,它们也不会编译为可执行程序,它们提供一些诸如函数之类的东西,使其他项目也能使用这些东西。

crate 根则是 Rust 编译器的起始点,在 Cargo 中遵循的一个约定:src/main.rs 就是一个与包同名的二进制 crate 的 crate 根。同样的,Cargo 知道如果包目录中包含 src/lib.rs,则包带有与其同名的库 crate,且 src/lib.rs 是 crate 根。

提供一系列功能的一个或者多个 crate,一个包会包含一个 Cargo.toml 文件,包中可以包含至多一个库 crate,任意多个二进制 crate。

模块

模块是crate的下一级结构,用户可以通过编辑其私有性来改变其他模块可以访问的本模块内容。在 crate 根中,你可以声明一个mod,它有两种声明的方式:

  1. 使用 mod 声明模块,在之后的大括号中声明其内容,在模块中可以继续声明模块,也可以存放诸如函数等其他内容
mod a{mod a_1 {fn ta(){}}
}
  1. 使用 mod 声明模块后接上 ; 号。然后将其内容放在同名的 .rs 文件中
//main.rs
mod a;//a.rs
fn ta(){}

在声明一个模块后,和模块处于同一级的代码块可以直接调用该模块,但是你不能直接调用模块内部的内容,不论是子模块还是函数等内容,因为模块内部的内容默认是私有的,只有模块内部可以直接调用模块内部的内容,为模块内的内容加上pub可以让他能被直接调用

mod a{mod a_1 {fn ta(){}}
}
//如此引用是无效的,因为a_1不是私有的不能访问
crate::a::a_1::ta();mod a{pub mod a_1 {pub fn ta(){}}
}
//如此引用有效的,因为a_1和ta都是pub的可以访问
crate::a::a_1::ta();

在一个模块中,父级不能调用子模块的内容,因为子模块于父模块中其他内容在同一级;但是子模块可以调用父模块的内容

mod a{mod a_1 {fn ta(){//这是有效的a::a_1::tb();}};fn tb(){}//这是无效的a_1::ta();
}

我们可以使用 super 关键字直接定位到父级来避免书写方法所在路径的全程

mod a{fn ta(){//ta的父模块就是cratesuper::tb();};
}
fn tb(){}

USE

如果我们想要使用一个非 pub 模块中的内容,可以使用 use 关键字导入某一个模块,之后我们就可以使用它了,引用时,我们可以使用绝对路径或者相对路径来引用它

  • 绝对路径absolute path)从 crate 根开始,以 crate 名或者字面值 crate 开头。
  • 相对路径relative path)从当前模块开始,以 selfsuper 或当前模块的标识符开头。
mod a{mod a_1 {fn ta(){}}
}
//绝对路径
use crate::a::a_1;
//相对路径
use a::a_1;
//可以调用非pub的函数了
ta();

当有多个相同的模块被引入时,我们可以通过 as 关键字为每个模块创建别名来区别每个模块

use std::fmt::Result;
use std::io::Result as IoResult;fn function1() -> Result {
}fn function2() -> IoResult<()> {
}

如果将 pubuse 合起来使用,我们不仅将一个名称导入了当前作用域,还允许别人把它导入他们自己的作用域。

mod front_of_house {pub mod hosting {pub fn add_to_waitlist() {}}
}
pub use crate::front_of_house::hosting;
//外部代码现在可以通过新路径 本文件名称::hosting::add_to_waitlist 来调用 add_to_waitlist 函数

当需要引入很多定义于相同包或相同模块的项时,为每一项单独列出一行会占用源码很大的空间,我们可以使用嵌套路径将相同的项在一行中引入作用域

use std::{cmp::Ordering, io};
//上面的效果等同于
use std::cmp::Ordering;
use std::io;use std::io::{self, Write};
//上面的等同于
use std::io;
use std::io::Write;

如果希望将一个路径下 所有公有项引入作用域,可以指定路径后跟 *,glob 运算符:

use std::collections::*;

异常处理

rust使用 panic! 这个宏来实现异常处理,当执行这个宏时,程序会打印出一个错误信息,展开并清理栈数据,然后接着退出,通常是检测到一些类型的 bug,而且程序员并不清楚该如何处理它。

fn main() {panic!("crash and burn");
}
//运行结果
$ cargo run
thread 'main' panicked at 'crash and burn', src/main.rs:2:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Result

Result 枚举是用于处理可能发生错误的时候使用的一类枚举,它有OK和ERR两个值,T 代表成功时返回的 Ok 成员中的数据的类型,而 E 代表失败时返回的 Err 成员中的错误的类型

enum Result {Ok(T),Err(E),
}

一个使用它的例子是,打开一个系统文件,因为文件不一定的存在,也不一定可以成功打开,所以rust中打开文件的库函数的返回值是一个Result

use std::fs::File;
fn main() {let f = File::open("hello.txt");let f = match f {Ok(file) => file,Err(error) => panic!("Problem opening the file: {:?}", error),};
}

处理多种类型的错误

显然对于刚刚的例子我们不知道错误是找不到文件还是文件损坏等等,所以我们可以通过对于错误类型进行匹配来定位错误,一些错误的类型已经在rust中给我们封装完毕了

let f = match f {Ok(file) => file,Err(error) => match error.kind() {ErrorKind::NotFound => ();other_error => {panic!("Problem opening the file: {:?}", other_error)}},
};

为了简化代码 Result 类型定义了很多辅助方法来处理各种情况

use std::fs::File;fn main() {//这种情况直接输出错误let f = File::open("hello.txt").unwrap();//这种情况可以自定义报错信息let f = File::open("hello.txt").expect("Failed to open hello.txt");
}
//等同于下面的函数
fn main() {let f = File::open("hello.txt");let f = match f {Ok(file) => file,Err(error) => panic!("Problem opening the file: {:?}", error),};
}

传播错误

另一种处理错误的方式是,让调用者知道这个错误并决定该如何处理,我们可以通过传播错误来获得这个错误从而妥善的处理它

use std::fs::File;
use std::io::{self, Read};fn read_username_from_file() -> Result {let f = File::open("hello.txt");let mut f = match f {Ok(file) => file,Err(e) => return Err(e),};let mut s = String::new();match f.read_to_string(&mut s) {Ok(_) => Ok(s),Err(e) => Err(e),}
}

rust中可以使用 运算符来简化上述的操作

//这个表述和上文代码功能相同
fn read_username_from_file() -> Result {let mut f = File::open("hello.txt")?;let mut s = String::new();f.read_to_string(&mut s)?;Ok(s)
}

相关内容

热门资讯

三门峡市2025年度市直机关公... 转自:三门峡发布三门峡市2025年度市直机关公开遴选拟任职人员公示公告根据2025年度三门峡市市直机...
进一步加强环境资源审判裁判规则...   为进一步加强环境资源审判裁判规则指引,最高人民法院近日公开发布第46批共5件生态环境保护专题指导...
纪念爱因斯坦广义相对论公开首讲... 来源:新华社 新华社柏林6月15日电(记者黄燕)当地时间14日下午至15日凌晨,柏林天文馆基金会在位...
“微专业”“小而精” 探索人才... 转自:中国发展网中国发展改革报社记者 | 荆文娜过去,人们常会问刚考上大学的学生,“学的什么专业?”...
行业大咖共议电影未来:需要重新... 上证报中国证券网讯(记者杨翔菲王彭)在短视频冲击、观众口味升级、行业成本攀升的多重挑战下,中国电影产...
国家统计局分析5月份国内消费市... 转自:北京日报客户端6月16日上午,国新办举行新闻发布会,介绍2025年5月份国民经济运行情况。记者...
最高检去年核准追诉低龄未成年人... 界面新闻记者 | 翟瑞民2025年6月16日,最高人民检察院发布《未成年人检察工作白皮书(2024)...
武威:构建全方位水安全网   西北角·中国甘肃网记者 张振国  为全面提升水环境自动监测能力,确保国家地表水水质自动站稳定高效...
最新:伊朗对以色列发动第八轮导... 据伊朗塔斯尼姆通讯社16日报道,伊朗当天凌晨对以色列发动了新一轮导弹袭击。这是伊朗伊斯兰革命卫队“真...
东软集团等成立数智康养产业新公... 人民财讯6月16日电,企查查APP显示,近日,大连数智康养产业有限公司成立,法定代表人为王星辉,经营...
国家统计局付凌晖:推动城市更新... 观点网讯:6月16日,国家统计局新闻发言人付凌晖在国新办新闻发布会上表示,下阶段将推动城市更新和危旧...
【女装】行业市场规模:2024... 转自:前瞻产业研究院行业主要上市公司:江南布衣(3306.HK)、歌力思(603808)、太平鸟(6...
2025年廊坊经洽会丨展商、好... 转自:廊坊发布编辑:董昕
正明生物:广州化妆品代加工的领... 在广州化妆品代加工这片竞争激烈的商业蓝海中,佛山正明生物科技有限公司宛如一艘稳健前行的巨轮,凭借卓越...
国家统计局:我国外贸发展综合优... 人民财讯6月16日电,国家统计局新闻发言人、国民经济综合统计司司长付凌晖在国新办新闻发布会上表示,5...
创新药BD交易再迎新进展,科创... 截至2025年6月16日 11:13,上证科创板生物医药指数下跌0.83%。成分股方面涨跌互现,悦康...
热闻|雷军“官宣”!小米YU7... 转自:大众报业·齐鲁壹点6月16日信息,雷军在微博发文表示,小米YU7将于6月底发布。还有很多重磅新...
伊朗对以色列发动第八轮导弹袭击 新华社德黑兰6月16日电(记者陈霄 沙达提)据伊朗塔斯尼姆通讯社16日报道,伊朗当天凌晨对以色列发动...
邦泽创科IPO:员工专科及以下... Hehson财经上市公司研究院|财报鹰眼预警广东邦泽创科电器股份有限公司(以下简称“邦泽创科”)拟计...
华康洁净:董秘回应股价不涨及市... 投资者提问:作为该股的股东,想了解下公司股价近来一直不涨的原因,所属板块已经涨了近20%了,但该股一...