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 ...
随机推荐
- 动态扩展磁盘(LVM)
使用gtp格式磁盘为lvm类型 [root@elk-log-srv01 ~]# parted /dev/vdd GNU Parted 3.1 Using /dev/vdd Welcome to GNU ...
- 探秘神奇的运动路径动画 Motion Path
CSS 中有一个非常有意思的模块 -- CSS Motion Path Module Level 1,翻译过来也就是运动路径.本文将对 motion path 一探究竟,通过本文,你可以了解到: 什么 ...
- Methods
string.prototype.trim() The trim() method removes whitespace from both ends of a string. Whitespace ...
- 问题:dependencyManagement和dependencies有什么区别
dependencyManagement和dependencies有什么区别 一.Maven的包管理 在maven中,dependencyManagement.dependencies和depende ...
- flex 弹性盒模型的一些例子;
1.垂直居中 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- DonkeyID---php扩展-64位自增ID生成器
##原理 参考Twitter-Snowflake 算法,扩展了其中的细节.具体组成如下图: 如图所示,64bits 咱们分成了4个部分. 毫秒级的时间戳,有42个bit.能够使用139年,从1970年 ...
- python-文件操作练习-配置文件读取、修改、删除
文件操作练习:http://www.cnblogs.com/wupeiqi/articles/4950799.html global log 127.0.0.1 local2 daemon maxco ...
- 使用 cmake 来搭建跨平台的应用程序框架:C语言版本
目录 一.前言 二.示例代码说明 1. 功能描述 2. 文件结构 3. cmake 构建步骤 4. Utils 目录说明 5. Application 目录说明 三.Linux 系统下操作步骤 1. ...
- 一道codeforces题目引发的差分学习
Codeforces Round #688 (Div. 2) 题目:B. Suffix Operations 题意:给定一个长为n的数组a,你可以进行两种操作:1).后缀+1; 2)后缀-1: ...
- QFNU-ACM 2020.04.05个人赛补题
A.CodeForces-124A (简单数学题) #include<cstdio> #include<algorithm> #include<iostream> ...