Спасибо за перепост вопроса. В комментариях к другому вопросу было бы сложно привести пример кода.
Я вижу здесь 2 варианта:
Вариант 1:
Создать функцию calculate
на всех структурах с одинаковой подписью. В вашем примере нет входных параметров, только возвращаемое значение. Если это не так, все становится немного сложнее, и вариант 2 мог бы быть более подходящим.
Примечание: функции сцепления усложняют использование интерфейсов в Go. Возможно, вы захотите избавиться от этого.
Пример:
type qty interface{
calculate() qty // chaining can be problematic. best no return value here.
get() string // or whatever type get should return
}
func (ts *TradeService) calculate() qty {
ts.calculateA()
return ts
}
func (ts *TransferService) calculate() qty {
ts.calculateC()
return ts
}
func main() {
// Now this should
fmt.Println(qtyGetService(&Trade{q: "10"}).calculate().get())
fmt.Println(qtyGetTransferService(&Transfer{q: "10"}).calculate().get())
// or without chaining (if the return value is removed from `calculate`):
printVal(qtyGetService(&Trade{q: "10"}))
printVal(qtyGetTransferService(&Transfer{q: "10"}))
}
func printVal(service qty) {
service.calculate()
fmt.Println(service.get())
}
Иногда имеет смысл реализовать функцию в структуре, даже если она не требуется для удовлетворения интерфейса. Если существует сервис, который не нужно вычислять перед вызовом get
, просто создайте эту функцию:
func (ts *SomeService) calculate() {}
Теперь ее можно использовать как qty
интерфейс.
Вариант 2 :
Может также случиться так, что случаи не настолько однородны, и их сложнее объединить в одном интерфейсе.
Затем вы можете работать с несколькими интерфейсами и приводить структуру, чтобы проверить, реализует ли она интерфейс. Только тогда вызовите метод. Это более или менее похоже на проверку, имеет ли структура определенный метод или нет.
type calculatorA interface {
calculateA()
}
type calculatorB interface {
calculateB()
}
type getter interface {
get()
}
func main() {
service := qtyGetService(&Trade{q: "10"})
if ok, s := service.(calculatorA); ok {
s.calculateA()
}
if ok, s := service.(calculatorB); ok {
s.calculateB()
}
var val string
if ok, s := service.(getter); ok {
val = s.get()
}
fmt.Println(val)
}
Надеюсь, это применимо к вашему случаю и дает вам некоторые идеи.