Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic programming in Go?

I know that Go doesn't support templates or overloaded functions, but I'm wondering if there's any way to do some kind of generic programming anyway?

I have many functions such as these:

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

Is there any way to do this without having so much redundant code?

like image 718
laurent Avatar asked Feb 27 '13 05:02

laurent


Video Answer


2 Answers

The most of what you can achieve is usage of interface{} type, something like this:

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 function should also be tweaked to return interface{} value and not some wrapper like now.

Then in the client code you can do the following:

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

or

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

This will yield some runtime overhead though. I'd better stick with separate functions and try to restructure the code somehow.

like image 199
Vladimir Matveev Avatar answered Oct 20 '22 00:10

Vladimir Matveev


Here's a working example of how you could change your code.

Since you know what type you expect for the given name, you can write your Get method in a generic way, returning interface{}, and then assert the type at the call site. See the spec about type assertions.

There are different ways to emulate some aspects of generics in Go. There were lots of discussions on the mailing list. Often, there's a way to restructure code so it's less dependent on generics.

like image 44
Thomas Kappler Avatar answered Oct 19 '22 23:10

Thomas Kappler