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 说明了重新键入和覆盖过程的工作原理。