Go 中的通用编程?

Posted

技术标签:

【中文标题】Go 中的通用编程?【英文标题】:Generic programming in Go? 【发布时间】:2013-02-27 05:24:51 【问题描述】:

我知道 Go 不支持模板或重载函数,但我想知道是否有任何方法可以进行某种泛型编程?

我有很多这样的功能:

func (this Document) GetString(name string, default...string) string 
    v, ok := this.GetValueFromDb(name)
    if !ok 
        if len(default) >= 1 
            return default[0]
         else 
            return ""
        
    
    return v.asString


func (this Document) GetInt(name string, default...int) int 
    v, ok := this.GetValueFromDb(name)
    if !ok 
        if len(default) >= 1 
            return default[0]
         else 
            return 0
        
    
    return v.asInt


// etc. for many different types

有没有什么方法可以做到这一点而无需太多冗余代码?

【问题讨论】:

【参考方案1】:

您可以实现的大部分是interface 类型的使用,如下所示:

func (this Document) Get(name string, default... interface) interface 
    v, ok := this.GetValueFromDb(name)
    if !ok 
        if len(default) >= 1 
            return default[0]
         else 
            return 0
        
    
    return v

GetValueFromDb 函数也应该调整为返回 interface 值,而不是像现在这样的包装器。

然后在客户端代码中你可以执行以下操作:

value := document.Get("index", 1).(int)  // Panics when the value is not int

value, ok := document.Get("index", 1).(int)  // ok is false if the value is not int

但这会产生一些运行时开销。我最好坚持使用单独的函数并尝试以某种方式重组代码。

【讨论】:

【参考方案2】:

这里是working example,说明如何更改代码。

由于您知道给定名称的期望类型,您可以以通用方式编写 Get 方法,返回 interface,然后在调用站点断言类型。请参阅有关 type assertions 的规范。

在 Go 中模拟泛型的某些方面有不同的方法。邮件列表上有很多讨论。通常,有一种方法可以重组代码,从而减少对泛型的依赖。

【讨论】:

【参考方案3】:

在客户端代码中你可以这样做:

res := GetValue("name", 1, 2, 3)
// or
// res := GetValue("name", "one", "two", "three")

if value, ok := res.(int); ok 
    // process int return value
 else if value, ok := res.(string); ok 
    // process string return value


// or
// res.(type) expression only work in switch statement
// and 'res' variable's type have to be interface type
switch value := res.(type) 
case int:
    // process int return value
case string:
    // process string return value

【讨论】:

以上是关于Go 中的通用编程?的主要内容,如果未能解决你的问题,请参考以下文章

Go 语言中的通用类型(int / uint)相对于特定类型(int64 / uint64)有啥优势?

Golang 面向对象编程

编程实践Go 语言中的指针

编程实践Go 语言中的指针

Go语言中的函数式编程

一天一门编程语言设计一套Go语言中的 Stream API 接口代码实现