Я все еще нахожусь вокруг интерфейсов в Go, но я пишу пакет, который возьмет график структур и выведет их в stdout в виде дерева. Для этого я определил interface
, называемый TreeNode
, который содержит метод GetChildren
, который должен возвращать часть структур, реализующих TreeNode
. Таким образом, я могу откинуть дерево, начиная с root. то есть вот полное определение интерфейса:
type TreeNode interface {
GetName() string
GetChildren() []TreeNode
}
Я слышал, что это лучший способ "принимать интерфейсы и возвращать структуры". Что имеет большой смысл. Тем не менее, я начинаю сталкиваться с проблемами, когда пытаюсь реализовать эти методы на struct
. Вот полный пример:
package main
import "fmt"
type MyStruct struct {
Name string
Children []*MyStruct
}
type TreeNode interface {
GetName() string
GetChildren() []TreeNode
}
func PrintTree(root TreeNode) {
// Print the nodes recursively
fmt.Println(root.GetName())
// etc.
}
func main() {
child1 := &MyStruct{
Name: "Child 1",
}
child2 := &MyStruct{
Name: "Child 2",
}
root := &MyStruct{
Name: "Root",
Children: []*MyStruct{child1, child2},
}
PrintTree(root)
}
func (my_struct *MyStruct) GetName() string {
return my_struct.Name
}
func (my_struct *MyStruct) GetChildren() []*MyStruct {
return my_struct.Children
}
При вызове PrintTree
в main
компилятор жалуется, что
cannot use root (type *MyStruct) as type TreeNode in argument to PrintTree:
*MyStruct does not implement TreeNode (wrong type for GetChildren method)
have GetChildren() []*MyStruct
want GetChildren() []TreeNode
Это немного удивительно, так как интерфейс говорит, что GetChildren()
должен возвращать объекты, которые реализуют TreeNode
, а *MyStruct
делает реализацию TreeNode
. Но ясно, что мне чего-то не хватает в том, как компилятор справляется с такой ситуацией (где тип интерфейса необходим рекурсивно).
Если я приму совет компилятора (и совет , это похоже вопрос ) и измените реализацию MyStruct
на GetChildren
, чтобы вернуть []TreeNode
В реализации GetChildren()
появляется новая ошибка компилятора, говорящая
cannot use my_struct.Children (type []*MyStruct) as type []TreeNode in return argument
, что также является неожиданностью. Плюс, похоже, все согласны с тем, что я должен возвращать struct
s из методов вместо того, чтобы возвращать interface
s. Я определенно мог бы жить с возвратом []TreeNode
из этого метода, но я, должно быть, что-то упустил, потому что компилятор не в восторге.
Go Версия: go version go1.13.8 darwin/amd64