当我们定义了一个对象时,一般会创建一个方法方便外部初始化一个实例。如下面的例子:
type Client struct { timeout int64 dialFunc func() error healthCheck func() bool } func NewClient(timeout int64, dialFunc func() error, healthCheck func() bool) *Client { return &Client{ timeout: timeout, dialFunc: dialFunc, healthCheck: healthCheck, } }
外部调用NewClient来获取一个实例,NewClient方法需要给Client结构体每个参数都赋值,如果Client对象的参数有几十个的话,那么调用NewClient需要传入几十个参数,而且如果用户只是要更改其中一个参数,其他参数都想用默认的,也需要传入所有参数,非常的不方便。
优化的方法一种可以对每个参数设置一个Set方法,NewClient中每个参数都设置默认值,外部调用完NewClient后再调用SetXX方法。
如果想直接在NewClient中就一次性配置好,可以通过functional option来实现:
我们先定义配置选项option,option是一个func,入参是*Client实例,在里面我们可以修改实例的值。
type NewClientOptions func(c *Client)
然后我们修改NewClient方法的入参为不定长的option,我们先创建一个实例,值都是默认值,然后调用option,修改实例的值。
func NewClient2(opts ...NewClientOptions) *Client { client := &Client{ timeout: defaultTimeout, dialFunc: defaultDialFunc, healthCheck: defaultHealthCheckFunc, } for _, opt := range opts { opt(client) //opt是个方法,入参是*Client,内部会修改client的值 } return client }
最后我们定义几个option方法:
func WithTimeout(timeout int64) NewClientOptions { return func(c *Client) { c.timeout = timeout } } func WithHealthCheck(healthCheck func() bool) NewClientOptions { return func(c *Client) { c.healthCheck = healthCheck } } func WithDial(dialFunc func() error) NewClientOptions { return func(c *Client) { c.dialFunc = dialFunc } }
这样外部就可以更简单的调用NewClient方法了,我们自己定义一个myHealthCheckFunc,并通过WithHealthCheck包一下,然后作为参数传入就行了。
client := NewClient2(WithHealthCheck(myHealthCheckFunc), WithTimeout(10))
创建的client实例中timeout和healthCheck是我们自己定义的,而dialFunc是用默认的。
其实这种通过传入func来配置参数的方式是比较常见的,比如grpc在建立连接时的Dial方法,其实就是使用的这种方式。
grpcClient, err = grpc.Dial( serviceTarget(target), grpc.WithBalancer(b), grpc.WithCompressor(grpc.NewGZIPCompressor()), grpc.WithDecompressor(grpc.NewGZIPDecompressor()), grpc.WithDefaultCallOptions(grpc.FailFast(false)), grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(time.Second*5), grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient( otgrpc.OpenTracingClientInterceptor(opentracing.GlobalTracer(), otgrpc.LogPayloads()), unaryClientInterceptor, )), )
转自:https://blog.csdn.net/liyunlong41/article/details/89048382
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。