go - 如何创建具有多种返回类型的接口方法
问题描述
这是对这个问题的跟进:具有多种返回类型的接口方法
我有两个略有不同的结构。一个是关于交易结构的,另一个是关于转移结构的。目标是计算最后的数量。此外,交易结构应实现一些与传输结构不同的特定功能,反之亦然。最后他们都调用一个get()
函数并最终返回数量(类型字符串)。我不能来做这样的事情,qtyGetService(trade{}).calculateA().get()
并且qtyGetService()
可以get()
从两个结构中调用,但calculateA()
它是一种仅用于贸易结构的方法。接口看起来首先有望解决此类问题,但我面临该问题中描述的问题接口方法具有多种返回类型,接口中的方法必须返回特定类型。返回一个interface{}
也不是一个选项,因为我无法链接下面示例中所示的函数(甚至没有提到使用reflect
)。
package main
import (
"fmt"
)
type Trade struct {
q string
// many other attributes
}
type Transfer struct {
q string
// many other attributes
}
type TradeService struct {
q string
// some other attributes
}
type TransferService struct {
q string
// some other attributes
}
type GetQty struct {
q string
// some other attributes
}
func qtyGetTradeService(str *Trade) *TradeService {
// some processing on the initial struct
return &TradeService{
q: str.q + " TradeService ",
}
}
func qtyGetTransferService(str *Transfer) *TransferService {
// some processing on the initial struct
return &TransferService{
q: str.q + " TransferService ",
}
}
func (ts *TradeService) calculateA() *GetQty {
// some processing on ts
return &GetQty{
q: ts.q + " CalculateA ",
}
}
func (ts *TradeService) calculateB() *GetQty {
// some processing on ts
return &GetQty{
q: ts.q + " CalculateB ",
}
}
func (ts *TransferService) calculateC() *GetQty {
// some processing on ts
return &GetQty{
q: ts.q + " CalculateC ",
}
}
func (gq *GetQty) get() string{
// some processing on gq common to both trade and transfer
return gq.q + " CommonGet "
}
func main() {
// this works just fine
fmt.Println(qtyGetTradeService(&Trade{q: "10"}).calculateA().get())
fmt.Println(qtyGetTransferService(&Transfer{q: "10"}).calculateC().get())
// But this would be "better" to do something like this:
fmt.Println(qtyGetService(&Trade{q: "10"}).calculateA().get())
fmt.Println(qtyGetService(&Transfer{q: "10"}).calculateC().get())
}
游乐场链接:https: //play.golang.org/p/SBCs_O9SL0k
解决方案
感谢您重新发布问题。在另一个问题的评论中,很难提供代码示例。
我在这里看到了 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)
}
希望这适用于您的情况并给您一些想法。
推荐阅读
- c# - GMap.NET:从 C# 代码显示我在 Vb.Net 中的当前位置
- c++ - 如何根据字符串数量的输入在 C++ 中创建数组?
- html - 与CSS的边界独立边距?
- android - 在电容器离子/离子反应中隐藏 Android 启动画面
- laravel-5.6 - 验证 Laravel 5.6 中两个字段的唯一组合
- android - 我想知道喷气背包导航组件是否足以应付主要片段包含一个带有很多标记的 MapView 的情况?
- sql - 计算所有表记录计数的麻烦
- reactjs - 使用 useState 更新或创建 Element
- reactjs - React - 在第一次渲染之前初始化状态并访问状态
- powershell - 在 Teams 中禁用欢迎消息时出错