关键词:
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添加新的字段也不会影响之前的代码。
推荐阅读:
golang函数式选项(functionaloptions)模式(代码片段)
...农在新加坡】,欢迎关注。个人博客网站:Golang函数式选项(FunctionalOptions)模式概览最近阅读源码的时候看到一段不错的代码,但是当时却不是非常理解为什么这么写。我们先来看一下源代码:typeUserstruct IDstring Nam... 查看详情
函数式编程之-模式匹配(patternmatching)(代码片段)
模式匹配在F#是非常普遍的,用来对某个值进行分支匹配或流程控制。模式匹配的基本用法模式匹配通过match...with表达式来完成,一个完整的模式表达式长下面的样子:match[something]with|pattern1->expression1|pattern2->expression2|pattern3... 查看详情
学习go语言之装饰器模式(代码片段)
一,首先理解装饰器模式:动态的给一个对象增加一些额外的职责,这是在软件设计原则上面,一个功能装饰另一个功能,每个功能遵循同一个接口是这个模式的特征。二,定义对象接口和装饰抽象类1typeIDecorateinterface2Do()345//装... 查看详情
python--函数之推导式(代码片段)
5.12推导式l=[]foriinrange(1,11):l.append(i)print(l)#用列表推导式(一行搞定)l=[iforiinrange(1,11)]print(l)列表推导式可分为两种模式:循环模式:[变量(加工的变量)for变量initerable(可迭代对象)]筛选模式:[变量(加工的变量)for变量initerable(可迭代对象... 查看详情
golang设计模式之选项模式(代码片段)
有时候一个函数会有很多参数,为了方便函数的使用,我们会给希望给一些参数设定默认值,调用时只需要传与默认值不同的参数即可,类似于python里面的默认参数和字典参数,虽然golang里面既没有默认参数也没有字典参数,但... 查看详情
go的选项模式
...个结构体如下定义:我们需要初始化结构体,如果是其他语言,函数支持默认参数:但是,go语言函数不支持默认参数,同时即使go语言支持默认参数,但是如果配置项过多,那么每一个配置项都得写一个默认参数,也不现实。... 查看详情
golang函数式选项(functionaloptions)模式(代码片段)
概览最近阅读源码的时候看到一段不错的代码,但是当时却不是非常理解为什么这么写。我们先来看一下源代码:typeUserstruct IDstring Namestring Ageint Emailstring Phonestring GenderstringtypeOptionfunc(*User)funcWithAge(ageint)Option returnfunc(u*Us... 查看详情
go中设计模式之结构型模式(代码片段)
外观模式1.定义:外部与一个子系统通信必须通过一个统一的对象进行,为子系统中的一组接口提供一致界面。2.代码示例://定义对外APItypeAPIinterfaceTest()funcNewAPI()APIreturnapiImplnewMod()typeapiImplstructmmodfunc(aapiImpl)Test()a.m.mod()//需要交... 查看详情
设计模式之单例模式(代码片段)
目录一、概念二、饿汉式实现三、懒汉式实现一四、懒汉式实现二1、双重判断2、指令重排3、可见性五、懒汉式实现三1、加载时机2、线程安全一、概念JVM中,单例对象只有一个实例存在。二、饿汉式实现publicclassSingletonprivatestat... 查看详情
单例设计模式之懒汉式(代码片段)
classSingletonprivatestaticSingletoninstance=null;privateSingleton()publicstaticSingletongetInstance()if(instance==null)synchronized(Singleton.class)if(instance==null)instance=newSingleton(); 查看详情
单例模式之懒汉式(代码片段)
单例模式之懒汉式:classLazyMan//单例模式之懒汉式,只有在需要的时候才被创建,//因为多个线程共享一个变量,所以会产生线程安全问题staticprivateLazyManlazyMan;/***因为要解决线程安全问题所以需要加上synchronized,但是这样*加上... 查看详情
java设计模式之单例模式与工厂模式(代码片段)
...🔥系列专栏:JavaSE精品总结文章目录 前言1、设计模式概念及分类2、单例模式2.1、饿汉式2.2、懒汉式2.2.1、懒汉式进阶版2.2.2、懒汉式之懒加载3、工厂模式3.1、书写实体类3.2、新建配置文件.properties3 查看详情
go设计模式—单例模式(代码片段)
单例模式采用了饿汉式和懒汉式两种实现,个人其实更倾向于饿汉式的实现,简单,并且可以将问题及早暴露,懒汉式虽然支持延迟加载,但是这只是把冷启动时间放到了第一次使用的时候,... 查看详情
go语言之正则表达式(代码片段)
go语言之正则表达式//regexppackagemainimport("fmt""regexp")funcmain()//需要匹配的模式//reg:=regexp.MustCompile("\w+")正则表达式中的需要转义reg:=regexp.MustCompile(`^z.*1$`)//返回匹配到的结果result:=reg.FindAllString("zhangsan1",-1)f 查看详情
go语言学习-函数(代码片段)
函数Go不是一门纯函数式的编程语言,但是函数在Go中是“第一公民”,表现在:函数是一种类型,函数类型变量可以像其他类型变量一样使用,可以作为其他函数的参数或返回值,也可以直接调用执行。函数支持多值返回。支... 查看详情
设计模式-装饰者模式(go语言描述)(代码片段)
什么是装饰者模式好久没有更新设计模式系列的博客了,今天我们来聊一聊装饰者模式,用过java的同学肯定对装饰者模式非常熟悉,就算你不知道什么是装饰者模式这概念,你也一定在代码中经常用到这个模式,为什么这么说呢?大家... 查看详情
设计模式之单例模式详解(java)(代码片段)
目录一、单例模式1.1饿汉式1.2懒汉式1.3DCL懒汉式(双重检验锁)1.4静态内部类1.5枚举一、单例模式单例模式的实现方式有许多种,重点是以下五种:饿汉式、懒汉式、双重校验锁(DCL懒汉式)、静态内部类... 查看详情
设计模式之单例模式详解(java)(代码片段)
目录一、单例模式1.1饿汉式1.2懒汉式1.3DCL懒汉式(双重检验锁)1.4静态内部类1.5枚举一、单例模式单例模式的实现方式有许多种,重点是以下五种:饿汉式、懒汉式、双重校验锁(DCL懒汉式)、静态内部类... 查看详情