Jacques Grelet
Jacques Grelet

Reputation: 9

Use a function with a scalar or slice

I would like use the function T_conv with a float or a slice of float. This example works with float as argument of T_conv:

func T_conv(T ...interface{}) []interface{} {
    var r []interface{} = make([]interface{}, len(T))
    for i, v := range T {
        fmt.Printf("Ind: %d Result: %v, type: %T\n", i, v, v)
        r[i] = v.(float64) * 1.00024
    }
    return r
}

func main() {
    v := T_conv(20.0)
    fmt.Printf("Result: %v, type: %T\n", v, v)
}

http://play.golang.org/p/YhdFoXyY_e

but fail at runtime with a slice as argument:

func main() {
    v := T_conv([]float64{20.0, 21.0})
    fmt.Printf("Result: %v, type: %T\n", v, v)
}

result:
Ind: 0 Result: [20 21], type: []float64
panic: interface conversion: interface is []float64, not float64

http://play.golang.org/p/3DP96EamxW

Upvotes: 0

Views: 143

Answers (1)

icza
icza

Reputation: 418127

Your approach, corrected

The problem in your case is if you pass a slice to your T_conv() function, inside T_conv() it will be the first element of the T slice parameter. The passed slice will not be identical to T. So if you want to make it work, then you have to use Type assertion to obtain the []float64 from T[0], and iterate over that.

Something like this: Go Playground

func T_conv(T ...interface{}) []interface{} {
    if len(T) == 0 {
        return []interface{}{}
    }

    if f, ok := T[0].(float64); ok {
        return []interface{}{f * 1.00024}
    } else if fs, ok := T[0].([]float64); ok {
        var r []interface{} = make([]interface{}, len(fs))
        for i, v := range fs {
            r[i] = v * 1.00024
        }
        return r
    }

    return nil
}

But I recommend the following solution.

Recommended approach

Your input problem is a perfect use-case for a function with variadic parameters:

func Conv(in ...float64) []float64 {
    out := make([]float64, len(in))
    for i, v := range in {
        out[i] = v * 1.00024
    }
    return out
}

Using it:

Note that you have to use ... when passing a slice to it. Read more: Passing arguments to ... parameters. You can even invoke it by enumerating the float numbers (without wrapping them in a slice).

v := Conv(1.0)
fmt.Printf("Result: %v, type: %T\n", v, v)

v = Conv([]float64{20.0, 21.0}...)
fmt.Printf("Result: %v, type: %T\n", v, v)

v = Conv(20.0, 21.0)
fmt.Printf("Result: %v, type: %T\n", v, v)

Output (try it on the Go Playground):

Result: [1.00024], type: []float64
Result: [20.0048 21.00504], type: []float64
Result: [20.0048 21.00504], type: []float64

Upvotes: 2

Related Questions