Отказ от ответственности. Единственное украшение, которое я сделал, - это встраивание структур, но одним из способов может быть определение типа для функции, которую вы хотите декорировать (не обязательно, но упростит подписи):
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
Недостатками этого является наличие декоратора для каждого типа функции. Плюсы , многие из которых мне нравятся , кодировка легко тестируется и отделена от исходной логики, поэтому она не требует каких-либо изменений в вашей исходной функции.
На самом деле, я думаю, что этот подход промежуточное программное обеспечение http использует для http.Handler
https://www.alexedwards.net/blog/making-and-using-middleware