英文:
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) //=> 这返回的是类型为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
结构体,因为它们具有相同的签名。我不确定我在这里做错了什么。
谢谢!
英文:
I am a beginner with go so bear with me on this. I have an interface defined as the following:
type DynamoTable interface {
Put(item interface{}) interface{ Run() error }
}
also I have a Repo
struct like so:
type TenantConfigRepo struct {
table DynamoTable
}
and i have a struct dynamo.Table
which has a Put
function defined like so:
func (table dynamo.Table) Put(item interface{}) *Put
and the Put
struct has a Run
function as follows:
func (p *Put) Run() error
What I am trying to do is have a generic DynamoTable
interface which will then be used for mocking and unit tests. however this is causing an issue with creating a new 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,
}
}
This however is throwing an error like so
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})
this is very strange for me because from what i see is the interface that has a Run() error
should be sufficient for the Put
struct since it has the same signature. I am not sure what i am doing wrong here.
Thanks!.
答案1
得分: 3
> 方法Put的类型错误(有func(item interface{}) *github.com/guregu/dynamo.Put,期望func(item interface{}) interface{Run() error})
你的函数返回一个*Put
。接口期望的是一个interface{Run() error}
。*Put
可能满足这个接口,但它们仍然是不同的类型。返回一个满足该接口的类型的函数签名与返回该接口的函数签名是不可互换的。
所以,首先给你的接口起一个名字。我们在两个地方引用它,你应该避免使用匿名接口(和结构)定义,因为它们没有固有的好处,会使你的代码更冗长、不干净。
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演示了这个重新类型化和覆盖过程的工作原理。
英文:
> wrong type for method Put (have func(item interface{}) *github.com/guregu/dynamo.Put, want func(item interface{}) interface{Run() error})
your function returns a *Put
. The interface expects an interface{Run() error}
. A *Put
might satisfy this interface, but they're still different types. A function signature returning a type that satisfies that interface is not interchangeable with a function signature returning that interface.
So, start by giving your interface a name. We refer to it in 2 places, and you should avoid anonymous interface (and struct) definitions because they have no inherent benefit and make your code more verbose and less DRY.
type Runner interface{
Run() error
}
Now update DynamoTable to use that interface
type DynamoTable interface {
Put(item interface{}) Runner
}
You say dynamo.Table
is outside of your control. But you can create a new type equal to dynamo.Table
and then override the put
method.
In overridden method, we'l cast our dynamoTable
back to dynamo.Table
, call the original dynamo.Table.Put
, and then return the result.
type dynamoTable dynamo.Table
func (table *dynamoTable) Put(item interface{}) Runner {
return (*dynamo.Table)(table).Put(item)
}
dynamo.Table
Can still return a *Put
because *Put
implements Runner
. The return value will be Runner
and the underlying type will be *Put
. Then the interface will be satisfied, and that error will be fixed.
https://go.dev/play/p/y9DKgwWbXOO illustrates how this retype and override process works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论