Golang中定义函数类型

发布于 2020-01-29 12:47:44 阅读 86

我自己写代码,定义类型要么是结构体要么是接口,而看有些大佬的代码,他们经常会定义一个类型是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();
}