golang 结构没有实现接口?
golang struct not implementing interface?
我是 go 的初学者,请多多包涵。我有一个定义如下的接口:
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
接口,然后将其用于模拟和单元测试。然而,这会导致创建新 Repo 时出现问题:
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
结构应该足够了,因为它具有相同的签名。我不确定我在这里做错了什么。
谢谢!
wrong type for method Put (have func(item interface{}) *github.com/guregu/dynamo.Put, want func(item interface{}) interface{Run() error})
你的函数 return 是 *Put
。该接口需要 interface{Run() error}
。 *Put
可能满足这个接口,但它们仍然是不同的类型。 函数签名return满足该接口的类型不能与函数签名return该接口互换。
因此,首先为您的界面命名。我们在 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
,然后 return 结果。
type dynamoTable dynamo.Table
func (table *dynamoTable) Put(item interface{}) Runner {
return (*dynamo.Table)(table).Put(item)
}
dynamo.Table
仍然可以 return 一个 *Put
因为 *Put
实现了 Runner
。 return 值将为 Runner
,基础类型将为 *Put
。然后接口就满足了,那个错误也就修复了。
https://go.dev/play/p/y9DKgwWbXOO 说明了重新键入和覆盖过程的工作原理。
我是 go 的初学者,请多多包涵。我有一个定义如下的接口:
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
接口,然后将其用于模拟和单元测试。然而,这会导致创建新 Repo 时出现问题:
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
结构应该足够了,因为它具有相同的签名。我不确定我在这里做错了什么。
谢谢!
wrong type for method Put (have func(item interface{}) *github.com/guregu/dynamo.Put, want func(item interface{}) interface{Run() error})
你的函数 return 是 *Put
。该接口需要 interface{Run() error}
。 *Put
可能满足这个接口,但它们仍然是不同的类型。 函数签名return满足该接口的类型不能与函数签名return该接口互换。
因此,首先为您的界面命名。我们在 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
,然后 return 结果。
type dynamoTable dynamo.Table
func (table *dynamoTable) Put(item interface{}) Runner {
return (*dynamo.Table)(table).Put(item)
}
dynamo.Table
仍然可以 return 一个 *Put
因为 *Put
实现了 Runner
。 return 值将为 Runner
,基础类型将为 *Put
。然后接口就满足了,那个错误也就修复了。
https://go.dev/play/p/y9DKgwWbXOO 说明了重新键入和覆盖过程的工作原理。