我是围棋的初学者,所以请耐心等待。我有一个定义如下的接口:
type DynamoTable interface {
Put(item interface{}) interface{ Run() error }
}
我也有一个这样的Repo
结构:
type TenantConfigRepo struct {
table DynamoTable
}
我有一个结构dynamo.Table
它有一个定义如下的Put
函数:
func (table dynamo.Table) Put(item interface{}) *Put
并且Put
结构具有如下Run
函数:
func (p *Put) Run() error
我正在尝试做的是拥有一个通用的DynamoTable
接口,然后用于模拟和单元测试。 但是,这会导致创建新存储库时出现问题:
func newDynamoDBConfigRepo() *TenantConfigRepo {
sess := session.Must(session.NewSession())
db := dynamo.New(sess)
table := db.Table(tableName) //=> this returns a type dynamo.Table
return &TenantConfigRepo{
table: table,
}
}
但是,这引发了这样的错误
cannot use table (variable of type dynamo.Table) as DynamoTable value in struct literal: wrong type for method Put (have func(item interface{}) *github.com/guregu/dynamo.Put, want func(item interface{}) interface{Run() error})
这对我来说很奇怪,因为从我所看到的情况来看,具有Run() error
的接口对于Put
结构来说应该足够了,因为它具有相同的签名。我不确定我在这里做错了什么。
谢谢!。
*github.com/guregu/dynamo.Put, want func(item interface{}) interface{Run() error})
您的函数返回一个*Put
。 接口需要interface{Run() error}
。*Put
可能满足此接口,但它们仍然是不同的类型。返回满足该接口的类型的函数签名不能与返回该接口的函数签名互换。
因此,首先为您的接口命名。 我们在 2 个地方引用它,您应该避免匿名接口(和结构)定义,因为它们没有固有的好处,并且使您的代码更冗长、更少 DRY。
type Runner interface{
Run() error
}
现在更新 DynamoTable 以使用该接口
type DynamoTable interface {
Put(item interface{}) Runner
}
你说dynamo.Table
是你无法控制的。 但是,您可以创建一个等于dynamo.Table
的新类型,然后重写put
方法。
在重写方法中,我们将dynamoTable
转换回dynamo.Table
,调用原始dynamo.Table.Put
,然后返回结果。
type dynamoTable dynamo.Table
func (table *dynamoTable) Put(item interface{}) Runner {
return (*dynamo.Table)(table).Put(item)
}
dynamo.Table
仍然可以返回*Put
,因为*Put
实现了Runner
。 返回值将Runner
,基础类型将*Put
。 然后接口将得到满足,并且该错误将被修复。
https://go.dev/play/p/y9DKgwWbXOO 说明了此重新键入和覆盖过程的工作原理。