【问题标题】:Can I create a function with same signature as another?我可以创建一个与另一个签名相同的函数吗?
【发布时间】:2020-03-17 19:20:32
【问题描述】:

我需要创建一个包装内部函数的函数,并且与内部函数具有完全相同的签名。我担心这是不可能的,因为 Go 不支持泛型,但也许使用 reflect 可以实现?以下是我想要的伪go:

func myFunc(a int, b string) (string, error) {
    return string(a) + b, nil
}

func wrapInner(inner interface{}) interface{} {
    argTypes := argsOf(inner)
    returnTypes := returnsOf(inner)

    wrapper := func(args argTypes) returnTypes {
        // do something with inner's args
        modArgs := doSomething(args)
        ret := inner(modArgs)
        // do something with the return
        modRet := doSomething(ret)
    }
    return wrapper
}

wrapped := wrapInner(myFunc)
val, err := wrapped(1, "b")

伪代码充满了错误,但想法是wrapInner 不知道inner 的签名。但是,它能够检查签名(可能使用reflect?)并创建一个向内部添加逻辑并具有与内部完全相同的签名的函数。这可能吗?

【问题讨论】:

  • 不,不是你所说的那样。您必须将其作为interface{} 返回,这意味着您必须使用反射来调用它。无法返回具有编译时未知签名的函数并直接调用它。
  • 正如其他人所说,这在 Go 中是不可能的。听起来您正在尝试解决问题,就好像您在使用泛型语言一样,也许如果您更详细地解释您要做什么,有人可以向您解释一个更像 Go 的解决方案?谢谢!

标签: go go-reflect


【解决方案1】:

您想要实现的是中间件模式。它通常用接口实现。您必须为要注释的每个函数手动实现中间件函数。

这是一个例子:

package main

import (
    "fmt"
    "strconv"
)

type Service interface {
    myFunc(a int, b string) (string, error)
}

type implService struct{}

func (s implService) myFunc(a int, b string) (string, error) {
    return strconv.Itoa(a) + b, nil
}

type loggingMiddleware struct {
    next Service
}

func (s loggingMiddleware) myFunc(a int, b string) (string, error) {
    fmt.Println(a, b)
    return s.next.myFunc(a, b)
}

func main() {
    var myservice Service = &implService{}

    myservice = &loggingMiddleware{
        next: myservice,
    }
    result, err := myservice.myFunc(1, "a") // prints 1 a
    fmt.Println(result, err)                // prints 1a <nil>

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多