【一起学Rust | 进阶篇】使用Bon快速生成builder,提高代码质量

文章目录

  • 前言
  • 一、安装Bon
  • 二、使用步骤
    • 1.为方法实现builder
    • 2.实现关联方法的builder
    • 3. 为结构体实现builder
    • 4. `Option<T>`字段成为可选项
    • 5. 实现`Into`转化
  • 参考文档


前言

在 Rust 编程语言中,除了广为人知的单例模式之外,工厂模式也是极为容易见到的一种设计模式。工厂模式在 Rust 中不仅出现频率高,而且还是官方大力推荐的写法。无论是 Rust 的标准库,还是众多的第三方库中,工厂模式都十分常见。

在以往进行编程的时候,如果想要实现工厂模式,通常需要编写一个结构体,接着再去实现新的方法以及构建方法。然而,现在有厉害的开发者发布了 Bon 库。这个库能够让实现工厂模式变得非常轻松,只需要在你的代码中添加相应的注解,就能够自动生成代码。这样一来,就可以省去大量的时间。

bon是一个非常实用的 Rust 库。这个库主要用于为函数和结构体生成一种在编译时就能进行检查的构建器。通过使用“bon”库,开发人员可以更加高效地构建函数和结构体,并且在编译阶段就能够发现潜在的错误,从而提高代码的质量和可靠性。此外,“bon”库还为函数和方法提供了带有可选参数和命名参数的惯用部分应用。这种特性使得函数和方法的调用更加灵活,可以根据不同的需求进行参数的选择和组合,进一步增强了 Rust 代码的可扩展性和可维护性。

类似于 Java 中的 Lombok 库,当你在项目中使用了它之后,类的属性的 getter 和 setter 等功能便无需你亲自去编写了。而这里提到的“bon”,它的作用在于使得 builder 不用你自己去编写。Lombok 库为 Java 开发者带来了极大的便利,通过简化代码的编写过程,提高了开发效率。同样,“bon”在特定的场景下也发挥着重要的作用,为开发者省去了编写 builder 的繁琐工作,让开发过程更加流畅和高效。


一、安装Bon

将此内容添加到你的Cargo.toml以使用这个库:

[dependencies]
bon = "2.2.1"

在非标准环境(no_std environments)中,可以通过将 default-features 设置为 false 来选择不使用 std 和 alloc cargo 特性。

或者在你的项目下执行以下命令

cargo add bon

版本用最新的就好了,这里只是个示例。

二、使用步骤

1.为方法实现builder

bon 可以通过构建器将带有位置参数的函数转换为带有 “具名” 参数的函数。只需在函数上方放置 #[builder] 宏即可轻松实现。这意味着使用 bon 这个工具,对于原本使用位置参数的函数,可以通过特定的方式(添加 #[builder] 宏)将其转换为使用具名参数的函数形式,使得函数调用更加清晰和灵活。例如,原本可能需要按照特定顺序传入参数的函数,现在可以通过指定参数名称来传入参数(链式调用)。

use bon::builder;
// 只需要下面一行注解
#[builder] 
fn greet(name: &str, age: u32) -> String {format!("Hello {name} with age {age}!")
}// 就可以实现链式调用
let greeting = greet().name("Bon").age(24).call();assert_eq!(greeting, "Hello Bon with age 24!");

这玩意儿也可以用在异步函数、可能出错的函数、泛型函数、“impl Trait”环境下,如果有问题你可以到git官方提交一个issue.

2.实现关联方法的builder

你也可以为关联方法生成构建器。要实现这一点,你还需要在 impl 代码块的上方添加一个 #[bon] 宏。

use bon::bon;struct Counter {val: u32,
}#[bon] // 在impl代码块上需要添加这个宏
impl Counter {#[builder] // 只要加了这个标记,调用时都是支持链式调用的fn new(initial: Option<u32>) -> Self {Self {val: initial.unwrap_or_default(),}}#[builder] fn increment(&mut self, diff: u32) {self.val += diff;}
}let mut counter = Counter::builder().initial(3).build();counter.increment().diff(3).call();assert_eq!(counter.val, 6);

在遵循 Rust 构建器的常见命名约定时,bon 对在 impl 代码块内部名为 new 的方法进行特殊处理。它会生成名称稍有不同的函数。

如果 #[builder] 被放置在名为 new 的方法上,那么生成的函数将通过builder()调用

对于不是名为 “new” 的任何其他方法以及任何自由函数通过call()调用。

3. 为结构体实现builder

bon支持经典模式,即使用 #[derive (Builder)] 语法对结构体进行标注以生成构建器。这意味着在 Rust 语言中,使用名为 bon 的 crate 时,可以通过在结构体上添加#[derive (Builder)]属性来自动生成一个构建器。这个构建器可以用于以一种更加灵活和可读的方式创建结构体的实例。例如,可以逐步设置结构体的各个字段,而不是一次性提供所有的参数。这样可以提高代码的可读性和可维护性,并且可以在构建过程中进行一些额外的验证或处理。例如

use bon::Builder;#[derive(Builder)] // 添加这一行就够了
struct User {id: u32,name: String,
}let user = User::builder().id(1).name("Bon".to_owned()).build();assert_eq!(user.id, 1);
assert_eq!(user.name, "Bon");

在结构体上使用 #[derive (Builder)] 会生成构建器 API,这个 API 与在结构体的 new () 方法上放置 #[builder] 属性且该方法的签名与结构体的字段相似的情况完全兼容。

一般来说,在结构体上使用 #[derive(Builder)] 和在函数/方法上使用 #[builder] 具有几乎相同的应用程序接口(API)。在整个文档中会同时使用这两种方式来提供示例。如果示例中只展示了一种语法的用法(例如 #[builder]),那么在没有明确说明的情况下,另一种语法(例如 #[derive(Builder)])很可能具有类似的效果。

#builder#[derive(Builder)]生成的构建器使用类型状态模式来确保所有必需的参数都被填充,并且不会重复调用相同的设置器,以防止意外的覆盖和拼写错误。如果有问题,将会产生编译错误。在构建器内部不存在潜在的 panic unwrap()调用。

4. Option<T>字段成为可选项

如果你的函数参数或结构体字段(简称成员)是 Option类型,那么生成的构建器不会强制为这个成员设置值,默认值为 None。

它还会生成两个设置器:一个接受 T 类型的值,另一个接受 Option类型的值。第一个设置器在调用处避免用 Some()包裹值。第二个设置器允许直接传入 Option类型的值。

use bon::Builder;#[derive(Builder)]
struct Projection {x: Option<u32>,y: Option<u32>,// 对非`Option`类型的成员使用注解。#[builder(default)]z: u32,
}// “x”和“y”都将被设置为“None”,“z”将被设置为“0”。
Projection::builder().build();Projection::builder()// 不使用`Some()`包裹值进行传递。.x(10)// 或者使用以“maybe_”为前缀的设置器,该设置器接受“Option”类型。.maybe_y(Some(20))// 对于`#[builder(default)]`和`Option<T>`生成的应用程序编程接口(API)是等效的。// 当调用`build()`时,`z`将被设置为`0`。.maybe_z(None).build();

5. 实现Into转化

如果你的成员类型是 String 或者 PathBuf,并且你需要将它们设置为硬编码的字符串字面量,那么你必须编写.to_owned() 或者.to_string() 或者.into()。

在这里插入图片描述
然而,你可以使用 bon 生成接受 impl Into 的设置器,以消除手动转换的需要。这可以通过对单个成员使用 #[builder (into)] 进行配置,或者对多个成员同时使用 #[builder (on ({类型}, into))] 进行配置。

use bon::Builder;
use std::path::PathBuf;// 所有类型为`String`的成员的设置器都将接受`impl Into<String>`。
#[derive(Builder)]                                                          
#[builder(on(String, into))]                                                
struct Project {name: String,description: String,// 此成员的唯一设置器将接受“实现了 Into<PathBuf> 的类型”。#[builder(into)]                                                       path: PathBuf,
}Project::builder()// “&str”在内部被转换为“String”。.name("Bon").description("Awesome crate 🐱")// “&str”在内部被转换为“PathBuf”。.path("/path/to/your/heart").build();

这只是 bon 所提供功能的一部分。你可以考虑阅读指南部分的其余内容,以充分发挥 bon 的强大功能并理解其做出的决策。

参考文档

  • bon官方文档

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32的寄存器深度解析

目录 一、STM32 寄存器概述 二、寄存器的定义与作用 三、寄存器分类 1.内核寄存器 2.外设寄存器 四、重要寄存器详解 1.GPIO 相关寄存器 2.定时器相关寄存器 3.中断相关寄存器 4.RCC 相关寄存器 五、寄存器操作方法 1.直接操作寄存器 2.使用库函数操作寄存器 六…

C++_18_重载运算符

重载运算符 意义&#xff1a;使该类对象使用该运算符时 与 该运算符本意不同 就是 起别的作用了 范围 在 重载的那个类中起效 语法&#xff1a; 返回值类型 operator 运算符(形参列表) {函数体; }举例&#xff1a; 注意 &#xff1a; ​ 形参中 使用 & &#xff08;引用&…

JavaWeb中处理 Web 请求的方式总结

文章目录 JavaWeb中处理 Web 请求的方式总结1. 原始的 Servlet 方式1.1. 环境搭建**创建 Maven 或 Gradle 项目**&#xff1a;**添加 Servlet 依赖**&#xff1a;**创建 Servlet 类**&#xff1a;**配置项目**&#xff1a;**配置 Tomcat**&#xff1a; 1.2. 路由机制1.3. 示例代…

CPU调度算法之SJF(短作业优先)

摘要 CPU的短作业优先&#xff08;SJF, Shortest Job First&#xff09;任务调度算法是一种旨在提高系统响应速度和效率的调度策略。该算法通过优先执行预计运行时间最短的任务&#xff0c;从而减少平均等待时间&#xff0c;提高系统的整体吞吐量。虽然SJF算法在许多场景下表现…

《垃圾回收的算法与实现》-算法-摘抄

本文是书籍《垃圾回收的算法与实现》的摘抄&#xff0c;不涉及算法源码及步骤讲解模块。 预备 对象由头(header)和域(field)构成。 头&#xff1a;对象中保存对象本身信息的部分&#xff0c;主要含有以下信息&#xff1a;对象的大小和种类。 域&#xff1a;对象使用者在对象…

【Java毕业设计】基于SpringBoot+Vue+uniapp的农产品商城系统

文章目录 一、系统架构1、后端&#xff1a;SpringBoot、Mybatis2、前端&#xff1a;Vue、ElementUI4、小程序&#xff1a;uniapp3、数据库&#xff1a;MySQL 二、系统功能三、系统展示1、小程序2、后台管理系统 一、系统架构 1、后端&#xff1a;SpringBoot、Mybatis 2、前端…

还不懂BIO,NIO,AIO吗

BIO&#xff08;Blocking I/O&#xff09;、NIO&#xff08;Non-blocking I/O&#xff09;和 AIO&#xff08;Asynchronous I/O&#xff09;是 Java 中三种不同的 I/O 模型&#xff0c;主要用于处理输入 / 输出操作。 一、BIO&#xff08;Blocking I/O&#xff09; 定义与工作原…

YOLOV3实现越界检测——智能安防

目录 应用前景 1. 安全监控系统 2. 家庭安防系统 3. 无人机监控 4. 交通管理 5. 无人驾驶技术 6. 大型活动现场 代码说明 1. YOLO 模型加载 2. 摄像头视频流捕获 3. 安全区域绘制 4. YOLOv3 目标检测 5. 过滤和标记人类目标 6. 入侵检测 7. 结果显示和退出 总结…

断点回归模型

断点回归&#xff08;Regression Discontinuity Design, RDD&#xff09;是一种准实验设计方法&#xff0c;用于评估政策或其他干预措施的效果。这种方法利用了一个清晰的阈值或“断点”&#xff0c;在这个阈值上&#xff0c;处理状态&#xff08;例如是否接受某种干预&#xf…

DevC++编译及使用Opencv

1.依赖 需要如下依赖&#xff1a; DevC11Opencv4.10.0CMake.exe 整个安装过程参考下面的文章&#xff1a;https://blog.csdn.net/weixin_41673576/article/details/108519841 这里总结一下遇到的问题。 2.问题 2.1 DevC安装路径 一定不要有空格&#xff01;&#xff01;否则…

tekton pipeline workspaces

tekton pipeline workspace是一种为执行中的管道及其任务提供可用的共享卷的方法。 在pipeline中定义worksapce作为共享卷传递给相关的task。在tekton中定义workspace的用途有以下几点: 存储输入和/或输出在task之间共享数据secret认证的挂载点ConfigMap中保存的配置的挂载点…

阿里中间件——diamond

一、前言 最近工作不忙闲来无事&#xff0c;仔细分析了公司整个项目架构&#xff0c;发现用到了很多阿里巴巴集团开源的框架&#xff0c;今天要介绍的是中间件diamond. 二、diamond学习笔记 1、diamond简介 diamond是一个管理持久配置&#xff08;持久配置是指配置数据会持久化…

全球热门剪辑软件大搜罗

如果你要为你的视频进行配音那肯定离不开音频剪辑软件&#xff0c;现在有不少音频剪辑软件免费版本就可以实现我们并不复杂的音频剪辑操作。这次我就给你分享几款能提高剪辑效率的音频剪辑工具。 1.福晰音频剪辑 链接直达>>https://www.foxitsoftware.cn/audio-clip/ …

研究生考试报名照片要求解读及被拒原因分析

全国硕士研究生考试报名近年来热度不减&#xff0c;一般在每年九月下旬开始&#xff0c;往往这个时候我们就要开始准备考研证件照了。但是有很多朋友手册考研可能会因为各种问题导致考研证件照不符合要求&#xff0c;那么今天报名电子照助手就带大家了解一下目前考研报名照片的…

参赛心得和思路分享:2021第二届云原生编程挑战赛2: 实现一个柔性集群调度机制

关联比赛: 2021第二届云原生编程挑战赛2&#xff1a;实现一个柔性集群调度机制 参赛心得 历时快两个月的第二届云原生编程挑战赛结束了&#xff0c;作为第一次参赛的萌新&#xff0c;拿下了28名的成绩&#xff0c;与第一名差了19万分&#xff0c;因为赛制时间太长&#xff0c…

计算机毕业设计选题推荐-作品分享交流平台(摄影、绘画、书法)-Java/Python项目实战(亮点:分享作品到微博、浏览历史、数据可视化)

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

局域网一套键鼠控制两台电脑(台式机和笔记本)

服务端&#xff08;有键盘和鼠标的电脑作为服务端&#xff09; 下载软件 分享文件&#xff1a;BarrierSetup-2.3.3.exe 链接&#xff1a;https://pan.xunlei.com/s/VO66rAZkzxTxVm-0QRCJ33mMA1?pwd4jde# 配置服务端 一&#xff0c; 二&#xff0c; 客户端屏幕名称一定要和…

yolo txt格式转coco json格式

yolo txt格式转coco json格式 **问题背景&#xff1a;**下载coco128数据集&#xff0c;使用yolov5模型进行推理并使用pycocotools.cocoeval 对预测结果进行精度计算。 coco128 下载地址&#xff1a;https://tianchi.aliyun.com/dataset/108650 解压缩cocozip之后可以看到如下的…

全面掌握信息架构:数字化转型的最佳实践与应用指南

在全球化和信息化高度发展的今天&#xff0c;企业正面临前所未有的挑战与机遇 数字化转型已成为各大企业保持竞争力的必由之路&#xff0c;而成功的数字化转型离不开稳健且灵活的信息架构。《信息架构&#xff1a;商业智能&分析与元数据管理参考模型》正是一本为企业提供全…

数学建模笔记—— 主成分分析(PCA)

数学建模笔记—— 主成分分析 主成分分析1. 基本原理1.1 主成分分析方法1.2 数据降维1.3 主成分分析原理1.4 主成分分析思想 2. PCA的计算步骤3. 典型例题4. 主成分分析说明5. python代码实现 主成分分析 1. 基本原理 在实际问题研究中,多变量问题是经常会遇到的。变量太多,无…