【问题标题】:function type parameter match in golanggolang中的函数类型参数匹配
【发布时间】:2018-02-13 09:05:12
【问题描述】:
package main

type gens func(args...interface{}) int

func sum1(a int,b int,c int) int {
    return a+b+c
}

func sum2(a...interface{}) int {
    ret := 0
    for _,v := range a {
        ret = ret + v.(int)
    }
    return ret
}

func main() {
    var a gens
    //a = sum1
    a = sum2
    println(a(1,2,3))
}

考虑上面的代码,sum2 可以工作,但 sum1 不能。

编译器说“不能在赋值中使用 sum1 (type func(int, int, int) int) 作为类型 gens”

我问的原因是因为我想编写一个接受变量参数函数的 goroutine 调度程序,除了将许多其他 func 参数重写为“args...interface{}”,我该怎么做

谢谢!

【问题讨论】:

  • 你不能。解释和解决方法见golang.org/doc/faq#convert_slice_of_interface
  • 感谢您的回复! @Volker
  • 首先,您可以清楚地看到您正在代码中传递接口片段。您应该传递接口并获取可以是切片的底层类型。因此,在sum1 中,您实际上传递的是 int 类型参数,这些参数无法使用接口切片进行包装。

标签: go goroutine


【解决方案1】:
type gens func(args...interface{}) int

您创建类型 gens,它是一个具有接口格式参数的函数。

sum1 不接受接口作为输入,所以它会给你错误

【讨论】:

  • 在我看来,定义一个参数为 "x...interface{}" 的函数,你可以传递任何类型,字符串,int 等。但是在“函数类型”中,它准确而明确地定义了一个你不能定义的类型。我在golang.org/doc/faq#How_do_I_get_dynamic_dispatch_of_methods找到答案
  • 一个接口不需要有类型,但类型gens是一个函数,其参数作为接口给出,函数返回一个int,sum1不起作用的原因是因为参数传递给将 1 作为接口求和,但 sum1 想要获得 3 个 int 值
【解决方案2】:
package main

type gens func(args...interface{}) int

func sum1(a...int) int {
    ret := 0
    for _,v := range a {
        ret = ret + v
    }
    return ret
}

func sum2(a...interface{}) int {
    ret := 0
    for _,v := range a {
        if _,ok := v.(int);ok {
            ret = ret + v.(int)
        }
    }
    return ret
}

func main() {
    var a gens
    println(sum2(1,'2',3))
    //a = sum1
    a = sum2
    println(a(1,2,3))
}

我像这样更改代码。只是更好的方式来展示我的思考和学习方式,请原谅我的游泳池英语T_T

在 sum2 func 中,参数实际上接受接口切片, 可以传任何类型的string,int等,见上,我传1,'2',3,现在可以了。

但在“函数类型”中准确且明确地定义了一个类型不能。 我无法运行 a = sum1 编译器说“不能在赋值中使用 sum1 (type func(...int) int) 作为类型 gens”

在 golang 数据结构中,interface{} 定义不同于其他,我认为定义一个类型会检查更严格! 我在http://golang.org/doc/faq#How_do_I_get_dynamic_dispatch_of_methods找到答案

【讨论】:

    【解决方案3】:

    您的函数 sum1sum2 具有不同的签名,因此 sum1 不能分配给类型 gens

    应尽可能避免使用interface{} 数据类型,因为在使用它时需要进行运行时类型转换。 (当然,仍然有正当理由这样做,例如解组等)

    您可以在此处阅读有关空接口的更多信息:http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go

    你可以在 sum2 中实现一个类型切换来处理不同的原始类型,然后添加它们:

    func sum2(a...interface{}) int {
        ret := 0
        for _,v := range a {
            switch d := v.(type) {
                case int, int32, int16:
                    ret += int(d)
                case float64,float32:
                   ret += float(d)
            }
            if _,ok := v.(int);ok {
                ret = ret + v.(int)
            }
        }
        return ret
    }
    

    或者你可以自己定义一个接口,然后在函数中接受这个接口

    type Integer interface{
        Int() int
    }
    
    func sum(i... Integer) {
        result := 0
        for _, v := range i {
            result += v.Int()
        }
    } 
    
    type myfloat float64
    func (m myfloat) Int() int {
        return int(m)
    }
    

    至于您的用例,建议使用最后一种方法。给每个任务一个像“run()”这样的行为,然后调度程序知道如何处理它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-30
      • 2018-06-28
      相关资源
      最近更新 更多