2012-08-11 46 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