zoukankan      html  css  js  c++  java
  • Golang中设置函数默认参数的优雅实现

    在Golang中,我们经常碰到要设置一个函数的默认值,或者说我定义了参数值,但是又不想传递值,这个在python或php一类的语言中很好实现,但Golang中好像这种方法又不行。今天在看Grpc源码时,发现了一个方法可以很优雅的实现,叫做 Functional Options Patter.通过定义函数的方式来实现

    比如我们以如下的构造函数为例说明下,用这个的好处

    func NewClient(address string,timeout,trynums int){}
    

    如果我们要实例化这个函数,timeout,trynums这个是必须要传的,那如果我不想传呢,一般可能是通过传对象(struct,map)或定义多个func,感觉都不太方便。

    func NewClient(address string){}
    func NewClientNoTimeout(address string,trynums int){}
    

    另一种传一个对象

    type Options struct{
        timeout int,
        trynums int
    }
    func NewClient(address string,opts Options){}
    

    用对象的形式,还得检查参数的合法性。比如传递了不存在的参数等。

    那么,我们看下用Functional Options Patter的方式,我写了一个简单的例子。

    package main
    
    import "fmt"
    
    //如何向func传递默认值
    
    type dialOption struct {
    	Username string
    	Password string
    	Service  string
    }
    
    type DialOption interface {
    	apply(*dialOption)
    }
    
    
    type funcOption struct {
    	f func(*dialOption)
    }
    
    func(fdo *funcOption) apply(do *dialOption){
    	 fdo.f(do)
    }
    
    
    func newFuncOption(f func(*dialOption))*funcOption{
    	return &funcOption{
    		f:f,
    	}
    }
    
    func withUserName(s string) DialOption{
    	return  newFuncOption(func(o *dialOption){
    		o.Username = s
    	})
    }
    
    func withPasswordd(s string) DialOption{
    	return  newFuncOption(func(o *dialOption){
    		o.Password = s
    	})
    }
    
    func withService(s string) DialOption{
    	return  newFuncOption(func(o *dialOption){
    		o.Service = s
    	})
    }
    
    //默认参数
    func defaultOptions() dialOption{
    	return dialOption{
    		Service:"test",
    	}
    }
    
    type clientConn struct {
    	timeout int
    	dopts dialOption
    }
    
    
    func NewClient(address string, opts ...DialOption){
    	cc :=&clientConn{
    		timeout:30,
    		dopts:defaultOptions(),
    	}
    	//循环调用opts
    	for _,opt := range opts {
    		opt.apply(&cc.dopts)
    	}
    
    	fmt.Printf("%+v",cc.dopts)
    }
    
    
    func main(){
    	NewClient("127.0.0.1",withPasswordd("654321"),withService("habox"))
    	NewClient("127.0.0.1",withService("habox"))
    }
    

    实例化时,通过func的方式来传递参数,也可以定义一些默认参数。如果以后要加,只需要更改很少的代码。
    而且,这种方式也不会传递不相关的参数,因为参数都在通过func的方式来修改的。
    唯一不好的地方可能是代码量相应的增加了。但是为了更优雅,这种做法还是值得的。

  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/smartrui/p/10324320.html
Copyright © 2011-2022 走看看