如何优雅的用golang封装配置项(Functional Options)

news2025/7/27 22:23:50

导读

最近要封装一个公共服务,涉及到配置项的地方总是找不到合理的方案,后来看了一下grpc在配置方面的封装,了解到原来是golang特有的Functional Options编程模式,今天分享给大家,希望你能用到,咱们直接来看代码

版本V1

alt 上面代码很容易,就是想初始化一下Server的配置选项,看起来好像没什么问题,其实问题非常多

  • 既然是初始化一些配置选项,那么当然是有的是必选项(Addr, Port),有的是可选项(Timeout,MaxConns),可选项不选的话还得给个默认值,显然这种方式是不满足的
  • 因为Server的属性都是公有方法,所以在外部任何地方都能修改属性,存在很严重的代码安全隐患
  • 上面Server和main函数虽然在同一个文件里面,其实Server是作为外部包使用的,下面的case都同理 既然上面无法满足咱们的需求,那么咱们就来修改一下

版本V2

既然配置项想要可选,那么咱们直接来个排列组合,调用不同的初始化方法即可只初始化自己想初始化的非必要选项 alt

  • Server的属性都是私有变量,的确是解决了包的属性被恶意篡改的行为,降低了代码风险
  • 但是排列组合太多,新增一个属性得新增指数级的方法,我上面的demo可选参数只有两个timeout和maxConns,但是如果有十几个可选参数,那么需要构造的初始化方法是非常多的
  • 一般情况下,对一个工具初始化都是统一的方法,这样处理的话初始化方法太多了,这一块的内容对使用者来说是不关心的,所以很不友好
  • 不想传的参数的默认值依然没有解决

版本V3

既然上面的例子封装的初始化方法太多,那么咱们就统一用一个方法来解决

alt
  • 这样做的确是解决了初始化方法太多的问题,但是太不灵活
  • 比如有100个可选参数,那而且你只想给最后一个可选参数赋值,但是前面99个你也得写,写的话具体写几? 我既然不关心前面99个可选参数,但是为什么还要写呢?这给人感觉就很奇怪

版本V4

咱们引入一个新的结构体Config,把必填的参数放在server里面,非必要的参数放在Congfig里面

alt
  • 解决了非必要参数可以有选择性的传一部分的问题,比如上面的case种只需要传Timeout
  • 也解决了不传的参数,能有默认值的问题,比如MaxConns不传的话 就是10
  • 但是如果只传必传的参数,那么在NewDefaultServer的时候,最后一个参数只能传nil,传nil的情况是不允许的,也是不友好的。
  • 用这种方式的话,Config的属性必须是公共变量,当然就有在运行的过程中属性被篡改的风险

版本V5

咱们来学一学java中的builder模式

alt
  • 其实就是在Server对象外部包了一层ServerBuilder,最后在ServerBuilder.Build()中返回了Server对象
  • 其实这个方法挺完美,满足了我们之前提的全部需求,但是问题在于,golang中的err处理,在这种方式中不是很好体现

版本V6

接下来咱们就看一看最后的终极解决方案 FUNCTIONAL OPTIONS模式

alt
  • 这个需要注意的是 type Option func(*Server)
  • 这个看起来比较整洁和优雅,对外的接口只有一个Create。
  • 相比于Builder模式,不需要引入一个Builder对象。
  • 对比配置化的模式,也不需要引入一个新的Config。

总结

Golang 由于语言本身的特性,不支持函数重载,函数式选项 的编程模式在一定程度上解决了其他语言需要通过函数重载解决的问题。 函数式选项 编程有以下优点:

  • 任意顺序传递参数
  • 支持默认值
  • 向后兼容性
  • 很容易维护和扩展

虽然 函数式选项 编程模式有很多优点,但是设计模式的存在都是为了弥补语言特性的缺陷的一种手段。它是为了解决代码扩展性的问题,往往是通过增加抽象牺牲了简单性,切勿过度使用。有些简单的配置,就不需要设计的这么通用了。

函数式选项模式的使用场景有哪些呢:

我们一般用来配置一些基础的服务配置,比如MySQL,Redis,Kafka的配置,很多可选参数,可以方便动态灵活的配置想要配置的参数。

本文由 mdnice 多平台发布

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

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

相关文章

Linux 文件权限之umask

目录一、文件默认创建权限二、文件默认创建权限掩码三、文件权限的修改本文主要讲解Linux中的文件默认创建权限相关的内容,涉及到的内容有:文件默认创建权限、文件默认创建权限掩码、文件访问权限的修改。 文件访问者共三类:文件所有者、文件…

忆享聚焦|人工智能、元宇宙、云计算、5G基站…近期热点资讯一览

“忆享聚焦”栏目第十二期来啦!本栏目汇集近期互联网最新资讯,聚焦前沿科技,关注行业发展动态,筛选高质量讯息,拓宽用户视野,让您以最低的时间成本获取最有价值的行业资讯。目录行业资讯1.ChatGPT火爆全球 …

值传递和引用传递

什么叫 值传递&引用传递值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,…

2023不伤人脉的全新商城分销,一劳永逸的消费分红

2023不伤人脉的全新商城分销,一劳永逸的消费分红 2023-02-24 11:52梦龙 2023不伤人脉的全新商城分销,一劳永逸的消费分红 如今是流量为王的时代,但是如何将流量转化为忠实客户是个难题。不再是单向的买卖关系,而是从对产品的关注…

CSS 盒子模型【快速掌握知识点】

目录 一、什么是盒子模型 二、边框border-color 三、边框粗细border-width 四、边框样式border-style 五、外边距margin 六、内边距padding 七、圆角边框 八、圆形 九、盒子阴影 一、什么是盒子模型 css盒子模型又称为框模型,盒子的最内部是元素的实际内容…

国家调控油价预测案例+源码

项目git地址:https://github.com/Boris-2021/Oil-price-control-forecast 使用已知的历史数据:日期、汇率、布伦特、WTI、阿曼原油价格,预测下一个调价周期中的汽油、柴油零售限价的调价价格。 一. 需求 1.1 需求说明 使用已知的历史数据&a…

Linux:makefile小结

1.初学者要掌握的基本知识 一条规则: 两个函数 三个变量 2.自己写的makefile,说明每条命令的作用: #指定源文件为*.c src $(wildcard *.c) #通过src生成中间需要的汇编文件名,把src中.c替换为.o obj $(patsubst %.c, %.o, $(src)) #…

编译原理【文法设计】—每个a后面至少一个b、ab个数相等,ab个数不相等的所有串

编译原理【文法设计】—设计每个a后面至少一个b、ab个数相等,ab个数不相等的文法为字母表Σ{a,b}Σ\{a,b\}Σ{a,b}上的下列每个语言设计一个文法 (a) 每个a后面至少有一个b的所有串 首先,每个a后面至少有一个b的正规式怎么写呢?每个a都需要…

华为OD机试题,用 Java 解【快递运输】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

16、变量、流程控制与游标

文章目录1 变量1.1 系统变量1.1.1 系统变量分类1.1.2 查看系统变量1.2 用户变量1.2.1 用户变量分类1.2.2 会话用户变量1.2.3 局部变量1.2.4 对比会话用户变量与局部变量2 定义条件与处理程序2.1 案例分析2.2 定义条件2.3 定义处理程序2.4 案例解决3 流程控制3.1 分支结构之 IF3…

MSTP的负载均衡实验

MSTP的负载均衡实验 拓扑图 配置思路 网路互联,交换机和网线配置网络设备 交换机 1. 初始化配置 2. 创建vlan 3. 交换机连接PC 设置模式为access, 并将端口加入对应vlan 交换机连接交换机端口 设置模式为trunk 并允许所有vlan通过 交换机连接路由器端口…

C/C++每日一练(20230224)

目录 1. 字符串排序 2. Excel表列名称 3. 颠倒二进制位 附录&#xff1a; 位移运算符 左移运算符<< 1.无符号 2.有符号 右移运算符>> 1.无符号 2.有符号 程序测试 1. 字符串排序 编写程序&#xff0c;输入若干个字符串。 要求: &#xff08;1&#x…

C++学习笔记-类和对象

##类与对象的思想 面向对象的特点&#xff1a;封装、继承、多态 面向对象编程的特点&#xff1a; &#xff08;1&#xff09;易维护&#xff1a;可读性高&#xff0c;即使改变了需求&#xff0c;由于继承的存在&#xff0c;只需要对局部模块进行修改&#xff0c;维护起来非常方…

华为OD机试题,用 Java 解【高矮个子排队】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

如何通过jar包得知maven坐标,以及如何替换依赖的依赖的版本

问题一&#xff1a;我只能得到这个jar包的名字&#xff0c;如果得知这个jar包的maven坐标&#xff08;groupId以及artifactId&#xff09;&#xff1f; 思路1&#xff1a;将jar包的名字&#xff08;去除版本号&#xff09;在mvn仓库中搜索&#xff0c;地址&#xff1a;https:/…

从ChatGPT出发:大模型与自然语言模型

目录引言基石故事的开始&#xff1a;Transformer异姓兄弟&#xff1a;GPT、Bert与GPT-2GPTBertGPT-2大力出奇迹&#xff1a;GPT3模型的进化&#xff1a;InstructGPTChatGPT代码库TransformerGPT-2GPT-3InstructGPT未来的工作安全性&有效性算力与标注代价的平衡参考文献引言…

LeetCode——2357. 使数组中所有元素都等于零

一、题目 给你一个非负整数数组 nums 。在一步操作中&#xff0c;你必须&#xff1a; 选出一个正整数 x &#xff0c;x 需要小于或等于 nums 中 最小 的 非零 元素。 nums 中的每个正整数都减去 x。 返回使 nums 中所有元素都等于 0 需要的 最少 操作数。 来源&#xff1a;力…

2023年2月《中国数据库行业分析报告》正式发布(含精彩内容概览)

为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况&#xff0c;从2022年4月起&#xff0c;墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》&#xff0c;持续传播数据技术知识、努力促进技术创新与行业生…

TongWeb8中应用常见异常

问题一&#xff1a;cookie异常字符报错如下 2022-06-14 11:07:31 [WARN] - java.lang.IllegalArgumentException: An invalid domain [.test.com] was specified for this cookie 2022-06-14 11:07:31 [WARN] - at com.tongweb.web.util.http.Rfc6265CookieProcessor.valida…

力扣-查询近30天活跃用户数

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;1141. 查询近30天活跃用户数二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.其他总结前言 一、题目&…