-1

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

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

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

4

1 回答 1

0

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

这是一个例子:

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>

}

于 2019-11-21T20:47:36.137 回答