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!.
CodePudding user response:
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.