c++中有重载,python中的函数参数可以省略,golang提供Options达到替代效果,几乎很多的框架中都有应用。
一般框架中似乎会定义一个叫做Options的结构体,感觉这个命名对初学者真不友好。记住Option是函数,Options是结构体。Options里面包含该框架的基本类型,而Option则代表操作其中一个或多个类型的函数。
type Option func(*Options)
感觉不叫Options反而更加易读。如Person结构体
type Person struct {
Name string
Age int
Gender int
Height int
Country string
City string
}
type Option func(*Person) //Option是对Person结构体操作的函数的别名
func NewPerson(opt ...Option) *Person{
p := new(Person)
p.Country = "china"
p.City = "beijing"
//上面提供默认值
for _, o := range opt{
o(p)
}
return p
}
func WithRegional(country, city string) Options {
return func(p *Person){
p.Country = country
p.City = city
}
}
person2 := NewPerson(WithPersonProperty("dongxiaojian", 18, 1, 180)
,WithRegional("china", "hebei"))
go-micrio中的例子,它的主要用到的类型/组件都封装在了Options中
type Options struct {
Auth auth.Auth
Broker broker.Broker
Cmd cmd.Cmd
Config config.Config
Client client.Client
Server server.Server
Store store.Store
Registry registry.Registry
Runtime runtime.Runtime
Transport transport.Transport
Profile profile.Profile
// 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
Signal bool
}
Service是interface的类型,Options()接口返回Options结构体(迷惑命名)
type Service interface {
// The service name
Name() string
// Init initialises options
Init(...Option)
// Options returns the current options
Options() Options
// Client is used to call services
Client() client.Client
// Server is for handling requests and events
Server() server.Server
// Run the service
Run() error
// The service implementation
String() string
}
对一个微服务Service初始化,要初始化其中的Options结构体
// NewService creates and returns a new Service based on the packages within.
func NewService(opts ...Option) Service {
return newService(opts...)
}
func newService(opts ...Option) Service {
// .....
options := newOptions(opts...)
//省略其他代码
}
func newOptions(opts ...Option) Options {
opt := Options{
Auth: auth.DefaultAuth,
Broker: broker.DefaultBroker,
Cmd: cmd.DefaultCmd,
Config: config.DefaultConfig,
Client: client.DefaultClient,
Server: server.DefaultServer,
Store: store.DefaultStore,
Registry: registry.DefaultRegistry,
Runtime: runtime.DefaultRuntime,
Transport: transport.DefaultTransport,
Context: context.Background(),
Signal: true,
}
//遍历Option函数来对Options结构体的opt对象初始化(迷惑的命名)
for _, o := range opts {
o(&opt)
}
return opt
}
比如我想用一个特定的Registry注册中心来初始化Options结构体,Registry函数是初始化操作Options结构体的函数之一,返回的是Option也就是函数
// Registry sets the registry for the service
// and the underlying components
func Registry(r registry.Registry) Option {
return func(o *Options) {
o.Registry = r
// Update Client and Server
o.Client.Init(client.Registry(r))
o.Server.Init(server.Registry(r))
// Update Broker
o.Broker.Init(broker.Registry(r))
}
}
//
service := micro.NewService(
//添加consul 作为注册中心
micro.Registry(consulRegistry),
)