首页 > 解决方案 > 从类型返回的类型的隐式接口

问题描述

我想解耦我的包裹。Go 谚语说“接受接口,返回结构”。我可以接受包含我在包 B 中定义的标题的 bookInterface,以免引用包含该类型的包 A。但是,如果该书包含具有标题的 Page 结构,我无法为该页面定义接口并在 bookInterface 中使用 PageInterface ......所以隐式接口仅适用于深度 1 还是这不同?

./prog.go:54:11: cannot use book (type *Book) as type BookInterface in argument to PrintBook:
    *Book does not implement BookInterface (wrong type for Pages method)
        have Pages() []Page
        want Pages() []PageInterface

示例代码:

package main

import (
    "fmt"
)

type Book struct {
   title string

   pages []Page
}


func (b *Book) Title() string {
    return b.title;
}

func (b *Book) Pages() []Page{
    return b.pages;
}

type Page struct {
   title string
}

func (p *Page) Title() string {
    return p.title;
}

type BookInterface interface {
 Title() string 

 Pages() []PageInterface 
}

type PageInterface interface {
   Title() string 
}

func PrintBook(book BookInterface ) {
    fmt.Println(book.Title());
    fmt.Println(book.Pages()[0].Title());
}


func main() {

    book := &Book{title: "my title", pages: []Page{Page{title: "my page title"}}}

    fmt.Println(book.Title());
    fmt.Println(book.Pages()[0].Title());
    
    
    PrintBook(book);
}

我不希望这个包直接链接到包A。这种数据结构有可能吗?是我想要做的吗,愚蠢的?我有哪些选择?

https://play.golang.org/p/zH9dzfF5ocB

标签: go

解决方案


您没有正确实现接口。您已将Pages接口中的签名明确定义为返回[]PageInterface。然而,您的实现返回[]Page. APage可以实现PageInterface,但[]Page不实现[]PageInterface(因为没有什么要实现的——它是一个接口而不是接口)。您需要更新Book. 这是您可以完成它的一种方法:

func (b *Book) Pages() []PageInterface {
    pages := make([]PageInterface, len(b.Pages))
    for i, p := range b.Pages {
        pages[i] = p
    }
    return pages;
}

推荐阅读