Golang 泛型編程初體驗
序言
眾所周知,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)不同的是兩個元素是否相等的判斷方式不一樣:
-
基本類型(int或string)直接通過”==“運算符來判斷;
-
用戶自定義類型萬千種種,數組切片算法中不可能知道,所以需要通過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的強大魅力,希望對讀者也有一定的啟發
來自:http://mp.weixin.qq.com/s/EEUtTykcrXhcM2hJT01SoQ