(re-post) generic sum in Go

huangapple go评论115阅读模式
英文:

(re-post) generic sum in Go

问题

我很抱歉。我不小心删除了之前的问题。这是我的第二次尝试。

我知道Go语言不支持泛型类型,但应该有一种方法可以实现这个。

我正在尝试使用接口和类型断言来添加任意类型的两个参数并返回结果。但是我卡在了以下问题上:

  1. 接口中没有定义 (+) 运算符。

  2. 不知道应该返回什么类型。

这是我之前的步骤:

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

这个函数可以给出正确的答案,但是它没有意义,因为我知道只会传递整数值。我想要一个函数,它不知道会传递什么类型的变量,并根据给定的变量类型返回相应的加法结果。

这是我的第二次尝试并且卡住了。

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)
}

请注意,我只会返回翻译好的部分,不会回答关于翻译的问题。

英文:

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)
// &lt;int Value&gt; &lt;int Value&gt;

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)

答案1

得分: 7

在Go语言中,没有运算符重载。你不能定义自己的+运算符。

正如你可能已经看到的,reflect.Value上也没有定义Add()方法。要使用+运算符,你需要获取值的底层类型,然后进行相加。你可以通过使用类型断言来实现这一点。

根据规范+运算符适用于整数、浮点数、复数和字符串。因此,你需要检查值是否属于这些类型之一,将其转换为该类型,然后进行相加。

以下是一个示例代码:

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("不同的类型,无法相加。")
    }

    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("该类型不支持相加。")
    }
}

请注意,返回类型是interface{},因为可能有不同的返回类型。

可以通过使用reflect.MakeFunc进行优化,如相关问题中所示(示例代码):

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))
}
英文:

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(&quot;Different kinds, can&#39;t add them.&quot;)
	}

	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(&quot;Type does not support addition.&quot;)
	}
}

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, &amp;addInt)
	makeFunc(AddFunc, &amp;addFloat)
	
	fmt.Println( addInt(1, 1) )
	fmt.Println( addFloat(1.0, 3.1415) )
}

huangapple
  • 本文由 发表于 2013年10月12日 02:45:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/19325152.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定