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)
}

相关内容

热门资讯

孙杨参赛4项 涵盖短中长距离 转自:天津日报  本报讯(记者 李蓓)昨天,即将在本周末开赛的2025全国游泳冠军赛报项名单出炉。3...
齐鲁品牌文化数智平台共建项目启...   张志恒 王鑫 济南报道  5月13日举行的“新质山东 品筑未来”2025年山东最具影响力品牌暨《...
云湖兰山服务综合体运营 转自:贵州日报 本报讯 5月13日,观山湖区环百花湖旅居推介会暨云湖兰山启幕式在观山湖区朱昌...
守好健康证的“健康关” 人都没到场,证就办好了?近日,有记者走访发现,一些医疗机构的健康证体检项目“缺斤少两”,规章制度形同...
“我的论文不是AI写的”(图) 转自:天津日报  有网友反映,自己原创的论文经过系统检测之后,竟被指出AI生成内容比例过高。据媒体报...
应用机器人与3D打印术行颌骨截...   刘通 通讯员 崔子昂 李鲲济南报道  近日,山东大学齐鲁医院口腔科颌面外科陈安威、王涛、韩亦冰及...
美股周二收盘点评:通货膨胀率下... 来源:宏观对冲陈凯丰Kevin截至4月份的12个月里,消费者物价指数上涨了2.3%,而截至3月份的1...
纽约汇市:美元下跌 美国通胀率...   彭博一项衡量美元强弱的指数兑所有G10货币均走低,此前发布的美国4月份消费者价格涨幅低于预期。投...
要为丘陵山区等研制急需急用的装... □四川日报全媒体记者 阚莹莹  近日,四川省农业农村厅发布2025年“天府良机”薄弱环节关键技术装备...
亮出低空经济发展的未来 □四川日报全媒体记者 高杲 李欣忆7款“四川造”低空产品小鹰-700飞机  ●是目前唯一国产的上单翼...
聆听“沧海龙吟” 共赏民歌之美... 转自:天津日报  本报讯(记者 张帆 摄影 曹彤)昨天,由首都图书馆发起并联合天津图书馆、河北省图书...
彩桥即将合龙   5月12日,宜宾市屏山县岷江二桥工地施工繁忙,建设者对桥梁最后几榀钢拱架进行吊装作业。岷江二桥是...
第二十届西博会5月25日开幕 ●拟邀请匈牙利、老挝为主宾国,浙江、青海为主宾省●拟特邀阿联酋担任大会合作伙伴●据初步统计,西部各地...
各美其美 美美与共 □四川日报全媒体记者 吴晓铃  在古老的历史长河中,留下帕特农神庙、雅典卫城等文明遗产的希腊是西方文...
“公证日记” 转自:天津日报  智慧公证  曾经,办理继承公证需要集齐一沓证明材料,群众要跑好几个部门;如今,滨海...
武清区扎实推进兴业富农 绘就乡... 转自:天津日报  初夏时节,灿烂的阳光夹杂着阵阵微风,深情抚慰着大运河畔的武清区南蔡村镇丁家瞿阝村。...
如皋农商银行:双向奔赴谋发展 ... 4月27日,如皋农商银行举办“跨境人民币赋能外贸企业发展”专题培训会。会议邀请跨境人民币业务优质企业...
泰州农商银行联合海陵区供销总社... 日前,泰州农商银行与泰州市海陵区供销总社在城中街道联合举办“政银携手进社区 惠民助农促消费”系列活动...
将虾苗卖到“小龙虾之乡” □四川日报全媒体记者 陈丽霏  5月,鲜活肥美的小龙虾大量上市,中江县黄鹿镇也迎来了一年中最繁忙的时...
建圈强链 四川农业明确产业“路... 5月11日,四川省大邑县现代农业(粮食产业)园区,工人在试验田中开展小麦新品的测产工作。 李旭 摄(...