序言

众所周知,Golang中不支持类似C++/Java中的标记式泛型,所以对于常用算法,比如冒泡排序算法,有些同学容易写出逻辑上重复的代码,即整型是第一套代码,字符串型是第二套代码,用户自定义类型是第三套代码。
重复是万恶之源,我们当然不能容忍,所以要消除重复,使得代码保持在最佳的状态。本文通过一个实际使用的简单算法的演进过程,初次体验了Golang的泛型编程,消除了重复代码,非常自然。

需求一:切片算法支持整型

今天是星期二,天气晴朗,万里无云,空气清新,我在办公室里听着音乐写着代码,开始了今天的工作。
“小哥,数组切片有没有add和remove函数,可以方便的将元素添加和删除?”
我抬头一看,是小明,就回答道:“什么类型的数组切片?”
小明说:“整型。”
”数组切片中的元素能不能有相同的?“我追问道。
”不能有相同的,我存的都是实体的Id。“小明肯定的回答。
“哦,这个简单,我过会提供一个Slice类,有Add和Remove方法,支持整型。”我有点自信的回答。
小明说完谢谢后,回到了办公位继续工作。

一个小时后,我写完了支持整型的切片算法(点击图片可查看大图):

小明看了我的实现后,说:”我试用一下?"

“丑媳妇不怕见公婆。“我请他试用。

小明用了5分钟,写了下面的代码:

从试用代码中可以看出,整型数组切片中最多有三个元素[1 2 3],元素2插入的第二次应该失败,同理元素2删除的第二次也应该失败,整型数组切片最后只剩下一个元素[1]。

go run运行代码后,日志如下:查看日志,结果符合期望。

需求二:切片算法支持字符串

周三下午,睡完午觉后精神有点小抖擞,浏览着邮件,突然发现公司又接了一个大单,于是吃了会精神食量。
”小哥,小哥!“
我抬头一看,是小雷。
”咋的啦,哥们?“我好奇的问道。
”听说你昨天实现了一个数组切片算法,已支持整型,我现在想用字符串型的数组切片算法,你能提供不?"小雷有点着急的问道。
我心里一想,Golang支持Any类型,即interface{},同时字符串和整型一样都可以直接用”==“运算符比较两个元素是否相等,所以你懂的。
”这个好实现,给我一首歌的时间就可以试用。“我说完后,就立刻修改起了代码。

两分钟后,我提供了新版本的代码:不难发现,改动很简单,只将三个地方的int改成了interface{},一切都是这么自然。

”哇塞,这么快?半首歌我还没听完。“小雷开森的说。
”简单设计,呵呵!“我们不约而同的说出了这个大家最爱说又最难做到的XP实践。

这次有了拷贝这个强大的武器,小雷两分钟就写完了试用代码:

从试用代码中可以看出,字符串型数组切片中最多有三个元素[hello golang generic],元素golang插入的第二次应该失败,同理元素golang删除的第二次也应该失败,字符串型数组切片最后只剩下一个元素[hello]。

查看日志,结果符合期望。

需求三:切片算法支持用户自定义的类型

今天周四,眼看明天就周五了,打算中午出去吃个自助餐提高一下生活质量,于是叫着小方开着车就杀出去了。由于在一点半之前要回到公司上班,所以匆匆地找了一家自助餐店。
“哇靠,人真多!”小方这样感叹道。
“这个店应该搞成多种模式,比如选取大家常吃的几种套餐(A,C,D),这样百分之七十的上班族都会直接领套餐,就不会白白浪费排队时间了。”我不着边际的边想边说。
“自助餐还是更有吸引力,顾客可以任意搭配,做到真正的私人订制,而套餐吃几次就腻味了。”小方反驳着对我说。
...
紧赶慢赶,终于,终于在一点半前回到了公司,于是又开始编码了。

“小哥,听说你实现了一个数组切片算法,既支持整型,又支持字符串型,我这还有一个小小需求。”
我抬头一看,是小方,就问“啥子需求?“
”我这边有自定义的struct类型,也想用数组切片算法。“小方大方的提出需求。
”这个嘛,这个嘛,有点难度!“我边思考边回应:”给我半个小时,让我试试。“
”好的,小哥。“小方说完后露出了惬意的笑。

我们先自定义一个类型:

Student类型有两个数据成员,即id和name。id是学号,全局我唯一;name是中文名字的拼音,可重复。

用户自定义类型和基本类型(int或string)不同的是两个元素是否相等的判断方式不一样:

  1. 基本类型(int或string)直接通过”==“运算符来判断;

  2. 用户自定义类型万千种种,数组切片算法中不可能知道,所以需要通过interface提供的方法进行两个元素是否相等的判断。

我们接着定义一个interface:

只要用户自定义的类型实现了接口Comparable,就可以调用它的方法IsEqual进行两个元素是否相等的判断了,于是我们实现了Student类型的IsEqual方法:

用户自定义的GetId方法是必要的,因为Id不一定就是数据成员,可能是由多个数据成员拼接而成。

我们将数组切片算法的易变部分”v == elem"抽出来封装成方法:于是数组切片的Add方法和Remove方法就变成:于是数组切片算法对于支持用户自定义类型的改动仅仅局限于isEqual函数了,我们通过接口查询来完成代码修改:半个小时后,我完成了代码,叫小方过来试用。

因为有拷贝这个强大的武器,小雷三分钟就写完了试用代码:从试用代码中可以看出,用户自定义类型的数组切片中最多有三个元素[{1001 xiao ming} {1002 xiao lei} {1003 xiao fang}],元素{1002 xiao lei}插入的第二次应该失败,同理元素{1002 xiao lei}删除的第二次也应该失败,用户自定义类型的数组切片最后只剩下一个元素[{1001 xiao ming}]。查看日志,结果符合期望。

小结

本文通过一种轻松愉快的方式阐述了实际使用的数组切片算法的演进过程,同时也是笔者使用Golang进行泛型编程的第一次旅行,再次领略了Golang中interface的强大魅力,希望对读者也有一定的启发

interface{} 泛型编程的更多相关文章

  1. C++ 模板与泛型编程

    <C++ Primer 4th>读书笔记 所谓泛型编程就是以独立于任何特定类型的方式编写代码.泛型编程与面向对象编程一样,都依赖于某种形式的多态性. 面向对象编程中的多态性在运行时应用于存 ...

  2. JAVA泛型编程笔记

    1介绍 Java泛型编程是JDK1.5版本后引入的.泛型让编程人员能够使用类型抽象,通常用于集合里面. 下面是一个不用泛型例子: List myIntList=new LinkedList(); // ...

  3. goalng nil interface浅析

    0.遇到一个问题 代码 func GetMap (i interface{})(map[string]interface{}){ if i == nil { //false ??? i = make( ...

  4. STL之父Stepanov谈泛型编程的发展史

    这是一篇Dr. Dobb's Journal对STL之父stepanov的采访.文中数次提到STL的基本思想.语言的特性.编程的一些根本问题等,非常精彩.这篇文章让我想去拜读下stepanov的大作& ...

  5. go 语言 interface{} 的易错点

    一,interface 介绍 如果说 goroutine 和 channel 是 go 语言并发的两大基石,那 interface 就是 go 语言类型抽象的关键.在实际项目中,几乎所有的数据结构最底 ...

  6. golang(10)interface应用和复习

    原文链接 http://www.limerence2017.com/2019/10/11/golang15/ interface 意义? golang 为什么要创造interface这种机制呢?我个人 ...

  7. Effective C++: 07模板与泛型编程

    C++ template机制自身是一部完整的图灵机(Turing-complete):它可以被用来计算任何可计算的值.于是导出了模板元编程(TMP, template metaprogramming) ...

  8. Go1.18中的泛型编程

    目录 目录 前言 泛型是什么 Go的泛型 泛型函数 泛型类型 类型集合 和接口的差异 总结 前言 经过这几年的千呼万唤,简洁的Go语言终于在1.18版本迎来泛型编程.作为一门已经有了14年历史的强类型 ...

  9. angular2系列教程(七)Injectable、Promise、Interface、使用服务

    今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我 ...

随机推荐

  1. HDU - 4027 Can you answer these queries?(线段树区间修改)

    https://cn.vjudge.net/problem/HDU-4027 题意 给一个有初始值的数组,存在两种操作,T=0时将[L,R]的值求平方根,T=1时查询[L,R]的和. 分析 显然不符合 ...

  2. 声源测向: TDOA-GCC-PATH方法

    收藏链接: http://www.funcwj.cn/2018/05/10/gcc-phat-for-tdoa-estimate/

  3. ASP.NET Identity V2简单介绍

    Microsoft.AspNet.Identity是微软在MVC 5.0中新引入的一种membership框架,和之前ASP.NET传统的membership以及WebPage所带来的SimpleMe ...

  4. oldboy s21day02

    1.猜数字,设定一个理想数字比如:66,让用户输入数字,如果比66大,则显示猜测的结果大了:如果比66小,则显示猜测的结果小了;只有等于66,显示猜测结果正确,然后退出循环.while 1: num ...

  5. docker 系列 - Docker 安装和Hub Mirror地址设置

    ======================为什么要使用Docker?======================= 容器真是个好东西, (1)容器能提供隔离性; (2)容器能打包环境, 简化部署难度 ...

  6. Java入门系列Java NIO

    jdk1.4中新加入的NIO,引入了通道与缓冲区的IO方式,它可以调用Native方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小.

  7. 【codeforces 870F】Paths

    Description You are given a positive integer n. Let's build a graph on vertices 1, 2, ..., n in such ...

  8. flex中使用white-space

    在微信小程序开发中,view设置为flex布局,但是flex的flex-wrap属性不起作用,如果起作用的话,默认值即no-wrap不换行.如果要测试view-scroll并且scroll-x 就没法 ...

  9. Django之CRM项目Day4-编辑客户 公私户 模糊查询

    1.增加客户 2.编辑客户 obj = models.Customer.objects.filter(pk=edit_id).first() form_obj = CustomerForm(insta ...

  10. web 安全知识点

    XSS 新手指南:DVWA-1.9全级别教程(完结篇,附实例)之XSS https://www.jianshu.com/p/303206ae2471 https://www.netsparker.co ...