2015年12月31日 星期四

golang Anonymous Functions and Closures 心得

golang Anonymous Functions and Closures 心得
===
這個方式可以讓你在同一個A func 的scope裡面,直接在某個函數裡面放入一個B func callback函數。
如果要在C語言裡面要放這種callback函數,必須在A func裡面某行先填入一個function pointer,然後等到A func返回以後才能有機會呼叫callback
但常常B func callback裡面想要直接調用A func裡面的變數。C語言裡面一定要動態配置才能將這變數儲存起來,返回以後傳入到B func callback,否則就需要動用到傳入到A的結構內容,如果沒有結構傳入A,就還要在呼叫A的地方配置一個結構,利用call by reference的方式傳回B func callback需要的資料。這樣不僅牽涉的很廣,也一再挑戰人類的懶惰。

go裡面不再需要了弄function pointer了,callback直接寫在已定義好為函數的變數上面。這樣子A func所屬的結構,可以直接在callback裡面去存取。不須動態配置、不須修改結構。對於追求agile的工程師來說,可以常常重構常常減少重複程式碼,真是大快人心。


  • 範例

原本這動作是要走訪所有的FileList[key],然後對每一個key做一種動作。此範例是有找到key就刪除。
func xxx(){
...
for key,value := range bj.Root.FileList {
_,ok := fileListMap[key]
if ok {
delete(bj.Root.FileList,key)
}
}
...
}

但是如果之後需要對 fileListMap[key] 其中的 value做判斷才決定要刪除的話,那就非得要整段程式碼複製貼上了。
別以為這短短的程式碼複製貼上很簡單容易,這只是一個範例所以很短。如果是有一堆複雜判斷的時候,複製貼上就代表這個程式碼逐漸腐敗。
過去C語言有上述的麻煩,因此就是copy past解決是最快。但是違反了agile精神,也就是不寫重複的程式碼。
如果是go就可以將重複的程式碼寫成函數walkInKey,並直接在上述的程式碼位置加上Closure。如下:
func (bj *BackupJson) walkInKey( w WalkFunc ){
for key,value := range bj.Root.FileList {
if w( key,value )==false {
delete(bj.Root.FileList,key)
}
}
}
func xxx(){
...
ks.walkInKey( func ( key string ,wasUpload bool)bool {
_,ok := fileListMap[key]
if ok {
return true
}
return false
})
...
}


這樣一來,如果有其他種判斷需要將key-value刪除。直接修改Closure內容return true or false就可以了。為golang又記上一筆agile friendly經驗


沒有留言: