我知道以前很多次都以各种形式问过这个问题,但我似乎无法以我所需要的方式来实现我正在学习的东西。任何帮助都是非常感谢的。
我有一系列的交换,它们都实现了大致相同的API。例如,它们每个都有一个GetBalance端点。但是,有些功能中有一到两个独特的东西需要访问。例如,exchange1在调用它的balance时需要使用client,而exchange2需要同时使用client变量和clientFutures变量。这是以后的一个重要注意事项。
我的背景是正常的。显然围棋在很多方面是不同的,所以我在这里被绊倒了。
我目前的实施和想法如下:
在exchanges模块中
type Balance struct {
asset string
available float64
unavailable float64
total float64
}
type Api interface {
GetBalances() []Balance
}在Binance模块中
type BinanceApi struct {
key string
secret string
client *binance.Client
clientFutures *futures.Client
Api exchanges.Api
}
func (v *BinanceApi) GetBalance() []exchanges.Balance {
// Requires v.client and v.clientFutures
return []exchanges.Balance{}
}在Kraken模块中
type KrakenApi struct {
key string
secret string
client *binance.Client
Api exchanges.Api
}
func (v *KrakenApi) GetBalance() []exchanges.Balance {
// Requires v.client
return []exchanges.Balance{}
}在main.go中
var exchange *Api现在我的想法是,我应该能够调用类似于exchange.GetBalance()的东西,它将从上面使用GetBalance函数。我也需要一些演员吗?我在这里迷路了。exchange可以是Binance,也可以是Kraken--在运行时决定。其他一些代码基本上调用一个GetExchange函数,该函数返回所需API对象的一个实例(已经在BinanceApi/KrakenApi中插入)
我知道继承和多态性不像其他语言那样工作,因此我完全搞不懂。我很想知道这里该去哪。Go似乎需要大量烦人的代码,这是其他语言在运行中所必需的。
发布于 2022-11-15 10:32:11
使用*exchanges.Api是相当奇怪的。您需要实现给定接口的东西。底层类型是什么(无论是指针还是值接收者)并不重要,所以使用exchanges.Api代替。
不过,还有另一个问题。在golang中,接口是隐式的(有时称为鸭子类型的接口)。一般来说,这意味着接口不是在实现它的包中声明的,而是在依赖于给定接口的包中声明的。有些人说,你应该自由地看待你所返回的价值观,但在你所接受的论点方面,你应该是限制性的。这可以归结为,在您的情况下,您将有类似于api包的东西,看起来有点像这样:
package api
func NewKraken(args ...any) *KrakenExchange {
// ...
}
func NewBinance(args ...any) *BinanceExchange {
}然后在你的其他包里,你会有这样的东西:
package kraken // or maybe this could be an exchange package
type API interface {
GetBalances() []types.Balance
}
func NewClient(api API, otherArgs ...T) *KrakenClient {
}因此,当有人查看这个Kraken包的代码时,他们可以立即判断所需的依赖项,以及它所使用的类型。另外的好处是,如果二进制或kraken需要额外的未共享的API调用,您可以进入并更改特定的依赖项/接口,而不会最终得到一个正在各地使用的庞大的集中化接口,但每次您只使用接口的一个子集。
这种方法的另一个好处是在编写测试时。有像gomock和mockgen这样的工具,这些工具允许您简单地通过以下操作为单元测试快速生成模拟:
package foo
//go:generate go run github.com/golang/mock/mockgen -destination mocks/dep_mock.go -package mocks your/module/path/to/foo Dependency
type Dependency interface {
// methods here
}然后运行go generate,它将在your/module/path/to/foo/mocks中创建一个模拟对象,实现所需的接口。在单元测试中,导入he mocks包,您可以这样做:
ctrl := gomock.NewController(t)
dep := mocks.NewDependencyMock(ctrl)
defer ctrl.Finish()
dep.EXPECT().GetBalances().Times(1).Return(data)
k := kraken.NewClient(dep)
bal := k.Balances()
require.EqualValues(t, bal, data)TL;DR
它的主旨是:
interfaces
实现自动化。
https://stackoverflow.com/questions/74443828
复制相似问题