Golang结构体没有实现接口?

huangapple go评论83阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2022年3月12日 06:06:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/71445114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定