具有任意接口的Golang传递函数参数

时间:2016-05-16 12:15:34

标签: function reflection go function-pointers

以下代码效果很好:

package main

import (
    "fmt"
)

func WrapperFunc(fn func(int,int) int) int{
    return fn(3,4)
}

func add(a,b int) int{
    return a + b
}

func main(){
    fmt.Println(WrapperFunc(add))
}

我想传递实现特定接口的其他参数。例如,我修改代码如下:

import (
    "fmt"
)

type RequestBody interface {
    GetDescription() string
}

type LoginRequest struct {
    Username string
    Password string
}

func (lr LoginRequest) GetDescription() string{
    return "cool function"
}

func WrapperFunc(fn func(int, int, RequestBody) int) int {
    lr := LoginRequest{}
    return fn(3, 4, lr)
}

func add(a, b int, lr LoginRequest) int {
    fmt.Println(lr.GetDescription())
    return a + b
}

func main() {
    fmt.Println(WrapperFunc(add))
}

它失败并出现以下错误:

cannot use add (type func(int, int, LoginRequest) int) as type func(int, int, RequestBody) int in argument to WrapperFunc

但是,当我没有实施GetDescription时,如下所示:

package main

import (
    "fmt"
)

type RequestBody interface {
    GetDescription() string
}

type LoginRequest struct {
    Username string
    Password string
}

func WrapperFunc(fn func(int, int, RequestBody) int) int {
    lr := LoginRequest{}
    return fn(3, 4, lr)
}

func add(a, b int, lr LoginRequest) int {
    return a + b
}

func main() {
    fmt.Println(WrapperFunc(add))
}

它因第二个错误而失败,因为未实现接口(如预期的那样)。

cannot use lr (type LoginRequest) as type RequestBody in argument to fn:
    LoginRequest does not implement RequestBody (missing GetDescription method)
 cannot use add (type func(int, int, LoginRequest) int) as type func(int, int, RequestBody) int in argument to WrapperFunc

因此,它理解,在WrapperFunc正文中,我只能使用fnintint来调用RequestBody interface来实现GetDescription 1}},但我还是无法在功能阶段传递它。我怎么能做到这一点?我想包装可以具有其类型可以更改的参数的函数。

1 个答案:

答案 0 :(得分:2)

问题是WrapperFunc()需要函数类型的值:

func(int, int, RequestBody) int

您尝试将add传递给具有函数类型的文件:

func(int, int, LoginRequest) int
如果两者具有相同的参数和结果类型,则

2 function types是相等的。这在上面提到的两种函数类型中不成立:RequestBodyLoginRequest是不同的类型,因此具有这些参数的函数类型是不同的类型。

如果您更改其参数以匹配所需类型,则只能将add传递给WrapperFunc()

func add(a, b int, lr RequestBody) int {
    fmt.Println(lr.GetDescription())
    return a + b
}

现在add()fn的参数中与WrapperFunc()具有相同的函数类型,因此您的代码将编译并运行。

输出(在 Go Playground 上试试)

cool function
7

备注:

lr中的add()参数RequestBody类型为LoginRequest,而非RequestBody。您可以像GetDescription()一样使用它,您可以将其称为WrapperFunc()方法。在LoginRequest中,您无需更改任何内容,因为RequestBody会实现fn(),因此可以使用值LoginRequest来调用RequestBody,并且类型为fn的接口值将自动隐式创建并传递给add()(在您的情况下为add())。

请注意,在RequestBody中,由于参数现在为LoginRequest,因此您无法引用LoginRequest的字段。如果实现接口的值确实是LoginRequest类型的值,您可以在需要时使用type assertion获取包装的<html ng-app="mynewapp"> <!-- CSS & JSS loading --> <body> <div id="myprevapp"> </div> </body> </html> 值。