Rust 设计模式:newtype

简介: Rust 中的 newtype 模式:用元组结构体封装基础类型(如 `struct Email(String)`),实现类型安全、语义清晰、校验可控与封装隐藏,零运行时开销,是保障代码健壮性的常用实践。(239字)


介绍一种简单但常见的 Rust 设计模式:newtype,这一模式在 Rust 中很常见,也算是一种常识性的术语了。newtype 是指将一个类型(比较典型的是基本类型,例如 i32, f64, String)包裹进一个元组结构体中,形成一个新的类型,通常会给这个新类型起一个更具有领域含义的名称。例如:

struct Email(String);

这种做法会有以下几点收益( 本文原文地址:https://laurence.blog.csdn.net/article/details/168145388 ):

1. 避免将参数搞混

在下面这个例子中你会注意到,amount 和 acc_no 都是整型,如果一不注意,就容易传错参数:

fn transfer(amount: i32, acc_no: i32) {
   
  // something...
} 

fn main() {
   
  let amount: i32 = 500;
  let acc_no: i32 = 6514;

  // swap args; works ok; incorrect result!
  transfer(acc_no, amount);    
}

使用 newtype 包裹之后,由于有类型检查,编译器可以帮助我们检查出这种错误:

struct Amount(i32);
struct AccNo(i32);

// pass structs as arguments
fn transfer(amount: Amount, acc_no: AccNo) {
   
  // do something
}

fn main() {
   
  transfer(Amount(500), AccNo(6514));
}

2. 增加易读性

这也是显而易见的,下面的示例都能印证这一点:

struct Meters(f64);
struct Centimeters(f64);
struct Inches(f64);
struct TotalLength(f64);

struct NodeIndex(usize);
struct EdgeIndex(usize);

3. 对包裹类型添加校验

这也很合理,作为特定值时,对基类型的格式、取值范围往往是有要求的,这些校验、格式化的方法最适合添加在 newtype 上,下面的示例是在初始化方法中添加了校验功能:

struct Email(String); 

impl Email {
   
    // validate when creating Email;
    pub fn new(value: String) -> Result<Self, String> {
   
        if value.contains('@') && value.contains('.') {
   
            Ok(Email(value))
        } else {
   
            Err("Missing the `@` and/or the `.`".into())
        }
    }
}

fn main() {
   
    let valid_email = Email::new("atlas@123.com".to_string());
    assert!(valid_email.is_ok());
}

4. 控制可见性 / 隐藏实现细节

newtype 的最后一种常见应用场景就是用来控制类型的可见范围。因为 newtype 是用一个新的类型去包裹一个已有的类型,利用定义类型时所处的位置(在哪个 crate 中)以及是否在前面添加 pub 关键字这些差别,就可以有效控制类型的可见性。例如下面这个例子:

pub struct UserName(pub String); // Username is public; String is public too;
pub struct Password(String); // Password is public; String remains hidden;
struct Email(String); // Email is only visible in crate.

实际上,通过控制原始类型和 newtype 类型的可见范围,可以创造出更多组合。在下一篇文章中,我们将会看到 Zed 项目中的一个真实而有力的 newtype 应用示例,在那个实例中就是利用了私有 newtype + 公开的 getter / setter 来控制某些全局状态的读写权限,请关注本公众号的下一篇文章。

最后,解释一下使用 newtype 是否会带来额外的开销,答案是:完全不会。我记得之前我们在《Rust “多态”的来龙去脉(下):dyn Trait ( Trait Object ) 到底是什么东西?》一文中介绍过结构体的内存布局:

根据《Programming Rust, 2nd Edition》第 9 章的介绍,Rust 要求结构体的各个字段统一存放在结构体的内存块中,每个字段保留其原始数据类型在内存中的布局,结构体并不会拆解字段的内存布局,不过 Rust 没有对结构体各个字段在内存中的顺序进行明确规定。

结构体占据的内存就是它所有字段占据的内存总和,结构体本身并不占据额外的内存,实际上,结构体“类型”在运行时基本不存在,字段名、字段类型这些定义只在编译期使用。编译完成后,访问字段被翻译成“起始地址 + 固定偏移量”的内存读写,运行时不需要查询任何结构体描述。所以,newtype 结构体是零成本的,其本身并不会额外占用内存,在编译时,编译器会生成它的 TypeId,这是我们唯一需要的信息,只在编译期有用和有效。


参考资料

目录
相关文章
|
20天前
|
缓存 边缘计算 监控
阿里云 CDN 内容分发网络服务租用价格表(一年 / 按月 / 按小时报价明细)
阿里云CDN通过就近分发缩短内容传输距离,显著改善访问速度。计费上以按量后付费为弹性补充、资源包预付费为长期优惠,流量与带宽两种计费模式按业务特征选择。HTTPS请求数、动态请求数等增值资源按需选购。做预算测算时,将流量/带宽费用与HTTPS、动态请求费用一并计入,监控用量、优化缓存命中率,在保障访问体验的同时有效控制CDN成本。
231 1
|
20天前
|
弹性计算 运维 安全
阿里云数字证书管理服务(原SSL证书)租用价格表(一年 / 按月 / 按小时报价明细)
阿里云数字证书管理服务,覆盖从个人站点到大型企业的HTTPS加密需求,证书主体以1/2/3年预付费订阅为主,托管、域名风险巡检增值服务支持按月订阅。选型核心是根据业务场景选择DV/OV/EV证书,区分单域名、通配符、多域名。预算核算时,除证书本身订阅费用,还要评估是否需要托管、风险巡检、部署次数包等增值服务。借助CAS CLI可以实现证书批量管理、自动化巡检,提前预警到期证书,保障网站HTTPS长期稳定安全。
143 0
|
20天前
|
API 开发工具 索引
Elasticsearch集群异常状态(RED、YELLOW)原因分析
Elasticsearch集群异常状态(RED、YELLOW)原因分析
92 2
Elasticsearch集群异常状态(RED、YELLOW)原因分析
|
20天前
|
运维 Java 编译器
【保姆级】JDK下载+安装+环境变量配置教程(所有版本汇总,2026最新版)
本文详解JDK安装与配置,以最新LTS版JDK 25为例,涵盖版本选择(优先LTS)、官网下载、图文安装步骤、环境变量配置(Path添加bin路径)及基础编译运行验证,新手可快速上手。
1132 1
|
20天前
|
人工智能 算法
拆解1688生意助手指令模板:B2B商家AI提效的执行层断点
本文深度拆解1688「生意助手指令模板库」(106条),揭示B2B AI工具落地的核心逻辑:提问质量决定输出价值。指出AI定位执行层、模板即接口协议、约束完整性决定可执行性,并强调商家需培养“表达纪律”,将隐性经验结构化为显性资产。
|
19天前
|
Rust IDE 开发工具
Zed 新特性:这次抄了IDEA,抄的很好
Zed新版本上线「选中即搜索」功能:终端或编辑器中选中文件名/路径,按快捷键唤起文件查找,搜索框自动填充选中文本,一键跳转,告别复制粘贴。对标JetBrains体验,细节处见真章。(238字)
106 0
|
20天前
|
人工智能 算法 程序员
以前创业的壁垒是你会不会做,2026年的壁垒是有没有人用你——2个大学生把训练视频做成App,半年赚50万
本文是「OPC一人公司通关手册」第37篇,拆解两个不会写代码的大学生如何用AI无代码工具,2周打造田径跑姿分析App:上传视频→AI逐帧诊断→给出改进建议。凭15万田径圈粉丝“预销售”,上线首月入7万,半年总收入约50万元,4万用户,4.7分好评。核心启示:受众先于产品、内容即冷启动、定价即产品、长尾SEO胜爆款词。(239字)
|
20天前
|
监控 IDE 安全
阿里云 Qoder CN 服务订阅租用价格表(一年/按月/按小时报价明细)
个人日常开发优先Pro套餐;经常做大型工程重构、代码批量迁移,选择Pro+。长期持续开发直接选择年付订阅,拿到折扣降低年均成本。团队根据实际开发人数采购席位,不要过量采购。企业私有化部署场景,提前评估50席位的最低采购门槛,合理规划预算。日常开发定期查看Credits消耗,监控编码智能体任务资源使用,及时采购资源包,避免任务中途中断。
176 0
|
20天前
|
弹性计算 运维 小程序
阿里云轻量应用云服务器租用价格表(一年/按月/按小时报价明细)
阿里云轻量应用服务器 适合个人建站、测试项目、小程序后端和中小型业务,价格最低、运维最省心;如果业务需要稳定独享带宽或高并发承载,建议升级到ECS标准实例。省钱的核心不是单纯比价,而是让配置与业务负载匹配,再叠加新用户权益、优惠券、大促节点和年付折扣。
240 0
|
20天前
|
Unix C++ Python
全层涌现公理——分层与同层涌现两大定律·分科只看纵向盲区
BSD全层涌现公理提出:涌现分两类——纵向(低层→高层,如粒子→生命)与横向(同层跨域,如医疗×犯罪→法医),二者实为同一引力的两个方向;纵×横构成涌现全空间,而学科纵向建制导致横向盲区。0元本体论公理级突破。(239字)
184 0