Golang仿函数实现方法及效率测试
来源:互联网 发布:网络问卷调查怎么弄 编辑:程序博客网 时间:2024/05/01 03:16
在C++ STL中,仿函数(functors)被大量用作改变算法的内在行为。
由于Golang不支持泛型,所以没法像C++那样灵活的使用仿函数。但是Golang有interface,函数是”一等公民”(可赋值给指定类型变量),因此,在Golang中实际上也可以像仿函数那样,通过具有相同参数和返回值的方法声明的不同对象,实现行为的差异化。
下面,详细讲述,Golang中的实现方法:
以下通过不同方法实现 Lesser(int,int)bool 和 Greater(int,int)bool的不同行为举例。
1. 通过interface实现
type Comparer interface { F(left, right int) bool}//create cmp object by namefunc CreateComparer(cmpName string) (r Comparer) { switch cmpName { case "": //default Lesser fallthrough case "Lesser": r = Lesser{} case "Greater": r = Greater{} default: //unsupport name panic(cmpName) } return}//Lessertype Lesser struct{}func (this Lesser) F(left, right int) (ok bool) { ok = left < right return}//Greatertype Greater struct{}func (this Greater) F(left, right int) (ok bool) { ok = right < left return}
2.通过函数对象实现
type CmpFunc func(left, right int) bool//create cmp object by namefunc GetCmpFunc(cmpName string) (r CmpFunc) { switch cmpName { case "": //default Lesser fallthrough case "Lesser": r = Less case "Greater": r = Great default: //unsupport name panic(cmpName) } return}//Lesserfunc Less(left, right int) (ok bool) { ok = left < right return}//Greaterfunc Great(left, right int) (ok bool) { ok = right < left return}
3.通过转调对象实现
type CmpObj byteconst ( CMP_LESS CmpObj = iota CMP_GREAT)func (me CmpObj) F(left, right int) (ok bool) { switch me { case CMP_LESS: ok = Less(left, right) case CMP_GREAT: ok = Great(left, right) default: panic(me) } return}
以下是3种方法的效率测试:
var ( cmp1 = CreateComparer("Lesser") cmp2 = GetCmpFunc("Lesser") cmp3 = CMP_LESS N = 100000000)func TestSize(t *testing.T) { fmt.Println("Interface", unsafe.Sizeof(cmp1)) fmt.Println("Func", unsafe.Sizeof(cmp2)) fmt.Println("Obj", unsafe.Sizeof(cmp3))}func Benchmark_Interface(b *testing.B) { for i := 0; i < N; i++ { cmp1.F(1, 2) }}func Benchmark_Func(b *testing.B) { for i := 0; i < N; i++ { cmp2(1, 2) }}func Benchmark_Obj(b *testing.B) { for i := 0; i < N; i++ { cmp3.F(1, 2) }}//Interface 16//Func 8//Obj 1//Benchmark_Interface-4 1000000000 0.55 ns/op//Benchmark_Func-4 2000000000 0.19 ns/op//Benchmark_Obj-4 2000000000 0.24 ns/op
结论如下:
用interface实现多态,会占用两个指针(16字节空间) 执行效率上 大概慢一倍
使用函数指针 占用1个指针(8字节) 执行效率最高 但使用起来不够灵活
使用转调对象 只需要1个字节 执行效率跟函数指针差不多
推荐使用第三种方法(转调对象)的方法,使用数值枚举标识多路分发逻辑,效率上几乎没有损失,对外部引用对象的空间需求也比较小。
我将以上测试代码放在这里,欢迎查阅:
https://github.com/vipally/glab/blob/master/lab5/lab5_test.go
0 0
- Golang仿函数实现方法及效率测试
- Linux统计行数方法及效率测试
- Golang继承中字段及方法的测试
- 效率测试函数代码
- java交换两个数的常见方法及效率测试
- [cookbook笔记三] colorReduce函数运行效率测试方法
- 代码效率测试方法
- 效率测试方法
- 内联函数与宏的实现及效率
- MYSQL 随机 抽取实现方法及效率分析
- Delphi函数调用效率测试
- golang实现python xrange方法
- list遍历方法及效率
- 使用Cruise和Mercurial实现个人预提交,提高生产效率及整体自动化测试成功率
- Golang 测试
- golang中对象方法作为函数指针
- Golang regexp包中的函数和方法
- Golang函数和方法的参数传递
- 1025. PAT Ranking (25)
- Spring MVC getServletConfigClasses和getRootConfigClasses
- 大三学android迷茫,求解
- forEach的用法
- 固定定位在Android机上的显示问题
- Golang仿函数实现方法及效率测试
- Android单元测试与模拟测试详解
- 我的第一节Java课
- 笨人学数学的方法
- matplotlib绘图蓝本
- 3066 快餐店
- Ubuntu+OpenCV+QT
- 关于面向对象
- Spring-05-Web-MVC注解应用