如何在Golang中装饰具有不同签名的功能?

时间:2019-03-20 16:41:39

标签: go decorator

我尝试应用这个著名的Golang decorators talk中的装饰器,但是它仅对他有用,因为他装饰的所有函数都附加到一个结构上,而他只是装饰一个Do()函数。我见过的所有其他教程也都采用这种方式,这很烦人。

我想用base58 / 64编码器功能修饰这些功能

func SpendTx(senderID, recipientID string, amount, fee utils.BigInt, payload string, ttl, nonce uint64) (rlpRawMsg []byte, err error)
func NamePreclaimTx(accountID, commitmentID string, fee uint64, ttl, nonce uint64) (rlpRawMsg []byte, err error)
func NameClaimTx(accountID, name string, nameSalt, fee uint64, ttl, nonce uint64) (rlpRawMsg []byte, err error)
...

如您所见,参数都是不同的,它们也是纯函数,没有附加到结构上。但是它们都返回[] byte和错误,因此应该可行。

1 个答案:

答案 0 :(得分:0)

免责声明,我唯一要做的修饰就是通过嵌入结构,但是一种方法可以是为您想要修饰的函数定义类型(并非绝对必要,但会使签名更简单):

type SpendTXFn = func SpendTx(senderID, recipientID string, amount, fee utils.BigInt, payload string, ttl, nonce uint64) (rlpRawMsg []byte, err error)

现在函数可以用这种类型进行对话,装饰器函数将包含与此类型相同的调用签名

func EncodedSpendTX(s SpendTX) SpendTX {
     return func(senderID, recipientID string, amount, fee utils.BigInt, payload string, ttl, nonce uint64) (rlpRawMsg []byte, err error) {
        // compute decorated result 
        res, err := s(senderID, recipientID, amount, fee, payload, ttl, nonce)
        if err != nil {
          return res, err
        } 
        // encode the res
        // return encoded res
     }
}

现在您可以装饰SpendTX功能:

decorated := EncodedSpendTX(originalSpendTx)

decorated(...) -> []byte, err

缺点是每种功能类型都有一个装饰器。 many with my favorite being的优点是,编码易于测试并且与原始逻辑分离,因此不需要对原始函数进行任何更改。


实际上,我认为这是go的http中间件通过http.Handler采取的方法

https://www.alexedwards.net/blog/making-and-using-middleware