Reputation: 1058
Here is an example that I created where I declare my first struct which is a Toolbox
that contains a slice Hammers
. I made an interface for Toolbox
and Hammer
so that others can use my functions without having to use my structs as long as they follow my interface implementation.
package main
import "fmt"
type ToolboxInterface interface {
GetHammers() []HammerInterface
}
type HammerInterface interface {
}
type Toolbox struct {
Hammers []Hammer
}
func (t Toolbox)GetHammers() []HammerInterface {
return []HammerInterface{t.Hammers}
}
type Hammer struct {
Color string
}
func CountHammersInToolbox(t ToolboxInterface) int {
hammers := t.GetHammers()
return len(hammers)
}
func main() {
toolbox := Toolbox{Hammers: []Hammer{
{Color: "Red"},
{Color: "Blue"},
{Color: "Green"}}}
fmt.Println(len(toolbox.Hammers))
fmt.Println(CountHammersInToolbox(toolbox))
}
My ToolboxInterface
declares the GetHammers()
method which I have implemented. However the CountHammersInToolbox method returns 1 instead of 3 as seen in the output.
uberswe$ go run scratch/main.go
3
1
I have tried different variations of this but I feel a bit stuck. I don't understand why it is returning 1 but I suspect that I am declaring my interface method in the wrong way.
How should I declare an interface that has a method to return a slice of a different interface?
Upvotes: 2
Views: 58
Reputation: 79556
There's nothing wrong with your interface definitions. The problem is that you're not properly converting []Hammer
to []HammerInterface
. It looks like you expect this to happen magically, but it doesn't.
In this bit of code:
func (t Toolbox) GetHammers() []HammerInterface {
return []HammerInterface{t.Hammers}
}
You're probably expecting that the returned result is a slice of 3 HammerInterface
s, but instead, you're getting a single HammerInterface
, which is actually a slice of three Hammers
s.
You must do this conversion manually. See this post for more details.
func (t Toolbox) GetHammers() []HammerInterface {
hammerInterfaces := make([]HammerInterface, len(t.Hammers))
for i, hammer := range t.Hammers {
hammerInterfaces[i] = t.Hammers[i]
}
return hammerInterfaces
}
In most real-world scenarios, your error would be caught by the compiler, because your slice of hammers (t.Hammers
) would not satisfy the HammerInterface
interface, but in your case, since that interface is empty, it matches any type, as interface{}
would.
Upvotes: 5