我自己写代码,定义类型要么是结构体要么是接口,而看有些大佬的代码,他们经常会定义一个类型是func
的,如下面代码所示,这个Option
的类型是一个函数,不是结构体,也不是interface
,这个在什么时候会这样声明呢?
我们本次讲解的代码如下所示
type options struct {
ConfigFile string
WWWDir string
}
type Option func(*options)
func SetConfigFile(s string) Option {
return func(o *options) {
o.ConfigFile = s
}
}
func SetWWWDir(s string) Option {
return func(o *options) {
o.WWWDir = s
}
}
func Init(ctx context.Context, opts ...Option) func() {
var o options
for _, opt := range opts {
opt(&o)
}
//TODO
}
//调用方
_ = app.Init(ctx,app. SetConfigFile(configFile), app.SetWWWDir(wwwDir))
那怎么使用这个Option
呢?因为Option
返回的是函数,我们直接可以在使用这个Option
的时候,直接调用这个函数即可。
那为什么要这样声明,为什么不直接定义一个方法直接对Option
这个结构体进行统一赋值(代码如下),而需要进行这样的骚操作?
type options struct {
ConfigFile string
WWWDir string
}
//获取options的指针
func GetConfig() *options{
return &options
}
//设置配置文件
func SetOptionSetConfigFile(config string) *options {
GetConfig().ConfigFile = config
}
当然不可否认,上面这样的操作也是可以的,但是前提是这些数据你都确定是有的,但是有些情况下,你可能有ConfigFile
这个配置,WWWDir
也没有相应的配置,理论上我们就不需要这些配置,直接不需要传递这些参数。
_ = app.Init(ctx)
那什么情况会使用这个操作呢?比如我们的框架中实现了很多第三方服务,我们在框架入口配置启动了某些服务,那么这些服务就会启动并生效,如果我们有些配置没有配,我们就不需要将这些服务启动起来。所以我们就可以用这样的骚操作。
其实这个函数类型就像php的匿名函数一样,比如
public function test(){
$func=function(){
return 'inner test'.PHP_EOL;
}
$func();
}