2013-10-11 2 views
3

http://play.golang.org/p/y7G1fMSoVaGolang, Go: (ре-пост) общая сумма в Go

Я так сожалею. Я случайно удалил свой предыдущий вопрос. Вот моя вторая попытка.

Я знаю, что Go не поддерживает общие типы, но должен быть способ сделать это.

Я пытаюсь добавить любые два аргумента и вернуть результат с помощью интерфейса и утверждения типа. Но я застрял на

  1. (+) не определена в интерфейсе

  2. не могу думать о какой тип я должен вернуться

Это мой предыдущий шаг.

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

Это дает мне правильный ответ, но это бесполезно, так как я знаю, что будут переданы целые значения. Я хочу функцию, которая не знает, что будет дано, и вернет добавление соответственно заданным типам переменных.

Вот моя вторая попытка и застревание.

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) 

Благодаря всегда.

ответ

5

В переходе нет перегрузки оператора. Вы не можете определить свой собственный +.

Как вы, наверное, уже видели, нет способа Add(), определенного на reflect.Value. Чтобы использовать +, вам нужно перейти к базовому типу значения, а затем добавить его. Вы можете использовать , используя утверждения типа.

В соответствии с spec+ определен для целых чисел, поплавков, комплексных значений и строк. Итак, вам нужно проверить, является ли значение одним из этих типов, преобразовать его в этот тип и , а затем добавить его.

Пример 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.") 
    } 
} 

Обратите внимание, что тип возвращаемого значения interface{}, как могут существовать различные типы возвращаемых.

Это может, как с this related question быть оптимизирована с помощью 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)) 
} 
+0

Большое спасибо x10000 –

-1

Этот пакет может сделать сумму и произведение большинства типов ломтиков: https://github.com/jhlr/slices У вас есть только позвонить slices.Sum(mySlice) ,

Смежные вопросы