Search code examples
govariadic-functions

Generic variadic argument 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 for variadic functions anyway?

I have many functions such as these:

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

func (this Document) GetInt(name string, defaults ...int) int {
    v, ok := this.GetValueFromDb(name)
    if !ok {
        if len(defaults) >= 1 {
            return defaults[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?


Solution

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

    func (this Document) Get(name string, defaults ...interface{}) interface{} {
        v, ok := this.GetValueFromDb(name)
        if !ok {
            if len(defaults) >= 1 {
                return defaults[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.