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的方式来修改的。
唯一不好的地方可能是代码量相应的增加了。但是为了更优雅,这种做法还是值得的。
Golang中设置函数默认参数的优雅实现的更多相关文章
- C++函数重载遇到了函数默认参数情况
一.C++中的函数重载 什么是函数重载? 我的理解是: (1)用一个函数名定义不同的函数: (2)函数名和不同参数搭配时函数会有不同的含义: 举例说明: #include <stdio.h> ...
- (转)python中函数参数中如果带有默认参数list的特殊情况
在python中函数参数中如果带有默认参数list遇到问题 先看一段代码 1 2 3 4 5 6 7 8 9 def f(x,l=[]): for i in range(x): ...
- 如何在ES5与ES6环境下处理函数默认参数
函数默认值是一个很提高鲁棒性的东西(就是让程序更健壮)MDN关于函数默认参数的描述:函数默认参数允许在没有值或undefined被传入时使用默认形参. ES5 使用逻辑或||来实现 众所周知,在ES5 ...
- 【转】Python函数默认参数陷阱
[转]Python函数默认参数陷阱 阅读目录 可变对象与不可变对象 函数默认参数陷阱 默认参数原理 避免 修饰器方法 扩展 参考 请看如下一段程序: def extend_list(v, li=[]) ...
- Python面试题目之Python函数默认参数陷阱
请看如下一段程序: def extend_list(v, li=[]): li.append(v) return li list1 = extend_list(10) list2 = extend_l ...
- C++函数默认参数(转)
在代码中使用到了函数的默认参数,在函数的定义和实现中都填写的默认参数,结果出现了错误: 代码: #ifndef FIRSTPAGE_H #define FIRSTPAGE_H #include < ...
- Python进阶-函数默认参数
Python进阶-函数默认参数 写在前面 如非特别说明,下文均基于Python3 一.默认参数 python为了简化函数的调用,提供了默认参数机制: def pow(x, n = 2): r = 1 ...
- Python中list作为默认参数的陷阱
在Python中,作为默认参数的一定要是不可变对象,如果是可变对象,就会出现问题,稍不注意,就会调入陷阱,尤其是初学者,比如我(┬_┬). 我们来看一个例子. def add(L=[]): L.app ...
- linux中probe函数传递参数的寻找(下)
点击打开链接 linux中probe函数传递参数的寻找(下) 通过追寻driver的脚步,我们有了努力的方向:只有找到spi_bus_type的填充device即可,下面该从device去打通,当两个 ...
随机推荐
- Ubuntu 18.04通过命令禁用/开启触控板
Ubuntu下经常遇到无法用快捷键关闭触控板的情况,博主的电脑安装Ubuntu18.04后便出现了该问题. 解决办法: 首先查看输入设备的id,命令行输入: xinput ,插鼠标与不插鼠标时,Tou ...
- git使用笔记(第一次)
背景:公司基于微服务的架构,前端的服务web只有一个.在并行完成不同需求的测试任务时,该服务会拉出不同分支,此时会碰到sit环境与其他测试小伙伴部署冲突的问题.解释下.需求1对应的服务web的A分支, ...
- 201871010118-唐敬博《面向对象程序设计(java)》第十一周学习总结
在博客园撰写博客(随笔),总结10周学习内容,作业格式要求如下: 博文名称:学号-姓名<面向对象程序设计(java)>第十一周学习总结(1分) 博文正文开头格式:(2分) 项目 内容 这个 ...
- day36_8_20数据库3外键
一.一对多 在数据库使用数据中经常遇到一对多的情况,以公司员工为例. 一张完整的员工表有以下字段: id name gender dep_name dep_desc . 以此建表得: id n ...
- 【作用域】词法作用域(静态作用域,如:js)、动态作用域(如:.bash脚本)
作用域 作用域是指程序源代码中定义变量的区域. 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限. JavaScript 采用词法作用域(lexical scoping),也就是静态作 ...
- <console>:14: error: not found: value spark import spark.implicits.
启动 ./spark-shell 出现问题 启动 hadoop, 并创建,解决 hadoop fs -mkdir /directory 解决了
- USACO Telephone Lines
洛谷 P1948 [USACO08JAN]电话线Telephone Lines https://www.luogu.org/problem/P1948 JDOJ 2556: USACO 2008 Ja ...
- JDOJ 1958 机器分配
JDOJ 1958: 机器分配 Description 某总公司拥有高效生产设备M台,准备分给下属的N个分公司.各分公司若获得这些设备,可以为总公司提供一定的盈利.问:如何分配这M台设备才能使国家得到 ...
- ibatis<iterate>标签
<iterate property="" 从传入的参数集合中使用属性名去获取值, 这个必须是一个List类型, 否则会出现OutofRangeException, ...
- 【2019.7.16 NOIP模拟赛 T1】洗牌(shuffle)(找环)
找环 考虑每次洗牌其实是一次置换的过程,而这样必然就会有循环出现. 因此我们直接通过枚举找出每一个循环,询问时只要找到环上对应的位置就可以了. 貌似比我比赛时被卡成\(30\)分的倍增简单多了? 代码 ...