I have a package in which I have two interfaces
package main
type A interface {
Close()
}
type B interface {
Connect() (A, error)
}
I have also two structures which implements these interfaces
type C struct {
}
func (c *C) Close() {
}
type D struct {
}
func (d *D) Connect() (*C, error) {
c := new(C)
return c, nil
}
Next I have a function which as a parameter wants an object which implements interface B
func test(b B) {
}
Finally, at the main() function I create D structure object and want to call test() function
func main() {
d := new(D)
test(d)
}
If I try to build that package I have an error.
cannot use d (type *D) as type B in argument to test: *D does not implement B (wrong type for Connect method) have Connect() (*C, error) want Connect() (A, error)
It is simple example of my code where I use external package and want to mock structures for tests. Is it any solution to use interfaces instead of types?
For implementing the interface there is one to concern about which is:
A Go type satisfies an interface by implementing the methods of that interface, nothing more. This property allows interfaces to be defined and used without having to modify existing code. It enables a kind of structural typing that promotes separation of concerns and improves code re-use, and makes it easier to build on patterns that emerge as the code develops.
The error you are getting because the struct D you are using as an argument to test function does not implement the interface. The reason behind this is that the function Connect you are using with receiver D is different. Since it has different return type:
func (d *D) Connect() (*C, error) { // the struct D does not implement the interface B because of wrong function definition to interface B function
c := new(C)
return c, nil
}
while if you want to implement the interface B the function definition along with its return type should match the function in interface B which is
type B interface {
Connect() (A, error)
}
So if you want to implement the interface the Connect method you are using should match the Connect method of the interface B
package main
type A interface {
Close()
}
type B interface {
Connect() (A, error)
}
type C struct {
}
func (c *C) Close() {
}
type D struct {
}
func (d *D) Connect() (A, error) {
c := new(C)
return c, nil
}
func test(b B) {}
func main() {
d := new(D)
test(d)
}
Check on Go Playground
Consider this simple interface to represent an object that can compare itself with another value:
type Equaler interface {
Equal(Equaler) bool
}
and this type, T:
type T int
func (t T) Equal(u T) bool { return t == u } // does not satisfy Equaler
The argument type of T.Equal is T, not literally the required type Equaler.
In Go, the type system does not promote the argument of Equal; that is the programmer's responsibility, as illustrated by the type T2, which does implement Equaler:
type T2 int
func (t T2) Equal(u Equaler) bool { return t == u.(T2) } // satisfies Equaler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With