2012-08-11 52 views
2

我正在編寫允許從數據庫訪問數據的代碼。但是,我發現自己對相似類型和字段重複相同的代碼。我怎樣才能寫相同的通用函數?在Go中編寫通用數據訪問函數

例如我想要達到的目標...

type Person{FirstName string} 
type Company{Industry string} 

getItems(typ string, field string, val string) ([]interface{}) { 
    ... 
} 

var persons []Person 
persons = getItems("Person", "FirstName", "John") 

var companies []Company 
cs = getItems("Company", "Industry", "Software") 

回答

2

所以,你肯定在正確的軌道上返回一部分零接口類型的想法。但是,當您嘗試訪問特定成員或調用特定方法時,您會遇到問題,因爲您不知道要查找哪種類型。這是類型斷言將非常方便的地方。爲了延長您的代碼位:

getPerson(typ string, field string, val string) []Person { 
    slice := getItems(typ, field, val) 
    output := make([]Person, 0) 
    i := 0 
    for _, item := range slice { 
     // Type assertion! 
     thing, ok := item.(Person) 
     if ok { 
      output = append(output, thing) 
      i++ 
     } 
    } 
    return output 
} 

那麼,做是執行通用搜索,然後處理掉僅是正確類型的那些項目。具體來說,類型斷言:

thing, ok := item.(Person) 

檢查是否變量itemPerson類型,如果是,則返回值與真,否則返回nil和false(從而檢查OK告訴我們,如果斷言成功)。

如果需要,您可以更進一步,並根據另一個布爾函數定義getItems()函數。基本想法是有getItems()運行函數傳遞每個元素在數據庫中,只有元素如果元素上運行該函數返回true添加到結果:

getItem(critera func(interface{})bool) []interface{} { 
    output := make([]interface{}, 0) 
    foreach _, item := range database { 
     if criteria(item) { 
      output = append(output, item) 
     } 
    } 
} 

(老實說,如果它是我,我會做一個混合的兩個接受標準函數,但也接受字段和值字符串)

+0

其實我會使用一個收集器功能,爲我追加。該函數可以關閉[]字符串切片,並執行附加到該切片的工作追加,如果類型斷言匹配。這將比getItem更加通用,它返回結果並且更安全,因爲「輸出」可能是一個類型化的片段。 – 2012-08-12 03:42:39

+0

是的,但不是你不能預測輸出類型的點,所以它必須是一個無界面(或其片)?也許我誤解了你提出的建議......? – joshlf 2012-08-12 03:48:02

+0

請參閱我的答案以獲得詳細解釋:-)。 – 2012-08-12 03:51:30

2

joshlf13有一個很好的答案。爲了保持一些額外的類型安全,我會稍微擴展一下。而不是一個critera函數,我會使用收集器功能。

// typed output array no interfaces 
output := []string{} 

// collector that populates our output array as needed 
func collect(i interface{}) { 
// The only non typesafe part of the program is limited to this function 
if val, ok := i.(string); ok { 
    output = append(output, val) 
} 
} 

// getItem uses the collector 
func getItem(collect func(interface{})) { 
    foreach _, item := range database { 
     collect(item) 
    } 
} 

getItem(collect) // perform our get and populate the output array from above. 

這有可能getItems通話後,不需要你遍歷你的接口{}片的好處,做另一個演員。

+0

如果您曾使用具有可縮放函數的語言來處理可迭代值,那麼收集器函數應該很熟悉。 – 2012-08-12 04:03:28