4

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

I am so sorry. I accidentally deleted my previous question. Here is my second try.

I know that Go does not support generic types but there should be a way to do this.

I am trying to add any type of two arguments and return the result using interface and type assertion. But I am stuck at

  1. (+) is not defined in interface

  2. can't think of what type I should return

This is my previous step.

   func Add(val1, val2 interface{}) int {
        new_a := val1.(int)
        new_b := val2.(int)
        return new_a + new_b
   }

This give me the right answer but this is useless since I know the integer values will be passed. I want a function that does not know what would be given and return the addition accordingly to the given variable types.

Here is my second try and get stuck.

http://play.golang.org/p/-_jvvs09nl

 func Add(val1, val2 interface{}) {

// var x interface{} = 7  // x has dynamic type int and value 7
// i := x.(int)           // i has type int and value 7

// a := reflect.ValueOf(val1)
// b := reflect.ValueOf(val2)
// fmt.Println(a, b)
// <int Value> <int Value>

type_val1 := reflect.TypeOf(val1)
type_val2 := reflect.TypeOf(val2)
fmt.Println(type_val1, type_val2)

result1 := val1.(type_val1) // ERROR : type_val1 is not a type
result2 := val2.(type_val2) // ERROR : type_val2 is not a type
fmt.Println(result1, result2)
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189

1 Answers1

7

In go there is no operator overloading. You can't define your own +.

As you probably have seen already, there is also no method Add() defined on reflect.Value. To use + you have to get to the underlying type of the value and then add it. You can do this by using type assertions.

According to the spec + is defined for integers, floats, complex values and strings. So you need to check whether the value is one of these types, convert it to that type and then add it.

Example on play:

func Add(a, b interface{}) (interface{}, error) {
    value_a := reflect.ValueOf(a)
    value_b := reflect.ValueOf(b)

    if value_a.Kind() != value_b.Kind() {
        return nil, fmt.Errorf("Different kinds, can't add them.")
    }

    switch value_a.Kind() {
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
            return value_a.Int() + value_b.Int(), nil
        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
            return value_a.Uint() + value_b.Uint(), nil
        case reflect.Float32, reflect.Float64:
            return value_a.Float() + value_b.Float(), nil
        case reflect.String:
            return value_a.String() + value_b.String(), nil
        default:
            return nil, fmt.Errorf("Type does not support addition.")
    }
}

Note that the return type is interface{} as there may be different return types.

This can, as with this related question, be optimized by using reflect.MakeFunc (example on play):

func main() {
    var addInt func(int, int) int64
    var addFloat func(float32, float32) float64

    makeFunc(AddFunc, &addInt)
    makeFunc(AddFunc, &addFloat)

    fmt.Println( addInt(1, 1) )
    fmt.Println( addFloat(1.0, 3.1415) )
}
Community
  • 1
  • 1
nemo
  • 55,207
  • 13
  • 135
  • 135