Go语言设计模式之函数式选项模式
Go语言设计模式之函数式选项模式
本文主要介绍了Go语言中函数式选项模式及该设计模式在实际编程中的应用。
为什么需要函数式选项模式?
最近看go-micro/options.go源码的时候,发现了一段关于服务注册的代码如下:
type Options struct {
Broker broker.Broker
Cmd cmd.Cmd
Client client.Client
Server server.Server
Registry registry.Registry
Transport transport.Transport
// Before and After funcs
BeforeStart []func() error
BeforeStop []func() error
AfterStart []func() error
AfterStop []func() error
// Other options for implementations of the interface
// can be stored in a context
Context context.Context
}
func newOptions(opts ...Option) Options {
opt := Options{
Broker: broker.DefaultBroker,
Cmd: cmd.DefaultCmd,
Client: client.DefaultClient,
Server: server.DefaultServer,
Registry: registry.DefaultRegistry,
Transport: transport.DefaultTransport,
Context: context.Background(),
}
for _, o := range opts {
o(&opt)
}
return opt
}
当时呢,也不是很明白newOptions
这个构造函数为什么要这么写,但是后面在微信群里看到有人也再发类似的代码问为什么要这么写,后来在群里讨论的时候才知道了这是一种设计模式–函数式选项模式。
可能大家看到现在也不是很明白我说的问题到底是什么,我把它简单提炼一下。
我们现在有一个结构体,定义如下:
type Option struct {
A string
B string
C int
}
现在我们需要为其编写一个构造函数,我们可能会写成下面这种方式:
func newOption(a, b string, c int) *Option {
return &Option{
A: a,
B: b,
C: c,
}
}
上面的代码很好理解,也是我们一直在写的。有什么问题吗?
我们现在来思考以下两个问题:
- 我们可能需要为Option的字段指定默认值
- Option的字段成员可能会发生变更
选项模式
我们先定义一个OptionFunc
的函数类型
type OptionFunc func(*Option)
然后利用闭包为每个字段编写一个设置值的With函数:
func WithA(a string) OptionFunc {
return func(o *Option) {
o.A = a
}
}
func WithB(b string) OptionFunc {
return func(o *Option) {
o.B = b
}
}
func WithC(c int) OptionFunc {
return func(o *Option) {
o.C = c
}
}
然后,我们定义一个默认的Option
如下:
var (
defaultOption = &Option{
A: "A",
B: "B",
C: 100,
}
)
最后编写我们新版的构造函数如下:
func newOption2(opts ...OptionFunc) (opt *Option) {
opt = defaultOption
for _, o := range opts {
o(opt)
}
return
}
测试一下:
func main() {
x := newOption("nazha", "小", 10)
fmt.Println(x)
x = newOption2()
fmt.Println(x)
x = newOption2(
WithA("沙"),
WithC(250),
)
fmt.Println(x)
}
输出:
&{nazha 小 10}
&{A B 100}
&{沙 B 250}
这样一个使用函数式选项设计模式的构造函数就实现了。这样默认值也有了,以后再要为Option添加新的字段也不会影响之前的代码。
推荐阅读:
Go语言设计模式之函数式选项模式的更多相关文章
- Golang 常见设计模式之选项模式
熟悉 Python 开发的同学都知道,Python 有默认参数的存在,使得我们在实例化一个对象的时候,可以根据需要来选择性的覆盖某些默认参数,以此来决定如何实例化对象.当一个对象有多个默认参数时,这个 ...
- Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)
jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...
- Go语言实践模式 - 函数选项模式(Functional Options Pattern)
什么是函数选项模式 大家好,我是小白,有点黑的那个白. 最近遇到一个问题,因为业务需求,需要对接三方平台. 而三方平台提供的一些HTTP(S)接口都有统一的密钥生成规则要求. 为此我们封装了一个独立的 ...
- golang中的选项模式
索引 https://waterflow.link/articles/1663835071801 当我在使用go-zero时,我看到了好多像下面这样的代码: ... type ( // RunOpti ...
- 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...
- JavaScript设计模式-单例模式、模块模式(转载 学习中。。。。)
(转载地址:http://technicolor.iteye.com/blog/1409656) 之前在<JavaScript小特性-面向对象>里面介绍过JavaScript面向对象的特性 ...
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...
- 设计模式:空对象模式(Null Object Pattern)
设计模式:空对象模式(Null Object Pattern) 背景 群里聊到<ASP.NET设计模式>,这本书里有一个“Null Object Pattern”,大家就闲聊了一下这个模式 ...
- C#设计模式之十三模板方法模式(Template Method Pattern)【行为型】
一.引言 “结构型”的设计模式已经写完了,从今天我们开始讲“行为型”设计模式.现在我们开始讲[行为型]设计模式的第一个模式,该模式是[模板方法],英文名称是:Template Method Patte ...
随机推荐
- 翻译:《实用的Python编程》InstructorNotes
实用的 Python 编程--讲师说明 作者:戴维·比兹利(David Beazley) 概述 对于如何使用我的课程"实用的 Python 编程"进行教学的问题,本文档提供一些通用 ...
- AI数学基础之:P、NP、NPC问题
目录 简介 P问题 NP问题 NP问题的例子 有些NP问题很难解决 NPC问题 NP-hard P和NP问题 简介 我们在做组合优化的时候需要去解决各种问题,根据问题的复杂度不同可以分为P.NP.NP ...
- 软件篇-06-SLAM小车Self Navigation
当SLAM小车能够以较高的精度运动到人为设置的目标点时,下一步就是把SLAM小车放到一个陌生的环境中,让它自己建图了.为什么?因为它已经是一只成熟的SLAM小车了. 我这里写的比较简单,刚写还没几 ...
- SSL证书及HTTPS服务器
1. 域名 在万网购买,略 2. 云服务器 阿里云购买,略 3. 安装lnmp 使用lnmp.org程序,略 4. 申请证书 阿里云-管理控制台-安全(云盾)-证书服务-购买证书证书类型: 免费型DV ...
- 【原创】简单解释一下,什么叫TLAB
[Deerhang] TLAB是全程Thread Local Allocation Buffer,中文大致的含义是:线程私有内存分配区.它存在的意义是提高线程在JVM堆上创建对象的效率.那么它是如何做 ...
- InnoDB解决幻读的方案——LBCC&MVCC
最近要在公司内做一次技术分享,思来想去不知道该分享些什么,最后在朋友的提示下,准备分享一下MySQL的InnoDB引擎下的事务幻读问题与解决方案--LBCC&MVCC.经过好几天的熬夜通宵,终 ...
- QFNU-ACM 2020.04.05个人赛补题
A.CodeForces-124A (简单数学题) #include<cstdio> #include<algorithm> #include<iostream> ...
- linux下将一个大的文件拆分成若干小文件
命令:split,例子: 以行数拆分 -l参数: split –l 50 原始文件 拆分后文件名前缀 说明:以50行对文件进行拆分,最后一个文件的行数没有50行以实际行数进行分配,比如有一个名为 wl ...
- IP包头部格式解析
IPv4首部一般是20字节长.在以太网帧中,IPv4包首部紧跟着以太网帧首部,同时以太网帧首部中的协议类型值设置为080016. IPv4提供不同,大部分是很少用的选项,使得IPv4包首部最长可扩展到 ...
- mitrproxy抓包微信小程序
mitmproxy mitmproxy is a set of tools that provide an interactive, SSL/TLS-capable intercepting prox ...