Implicit interface for type returned from a type?

Go proverb says “Accept interfaces, return structs”. I want to decouple novelapp package (the consumer) from the package novel (the provider) and use novel without importing via an interface. This works for Book interface with title function but I cannot substitute Page for PageInterface… why not?

what I wanted to achieve is to be able to drop in any package almost independent of each other and use main to glue the parts together.

Example Code:

// package novel
package novel

// Page ...
type Page struct {
    title string
}

func NewPage(title string) Page {
    return Page{title: title}
}

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

// Book ...
type Book struct {
    title string
    pages []Page
}

func NewBook(title string, pages []Page) *Book {
    return &Book{title: title, pages: pages}
}

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

// Pages ...
func (b *Book) Pages() []Page {
    return b.pages
}
// package novelapp
package novelapp

import "fmt"

// BookInterface ...
type BookInterface interface {
    Title() string

    Pages() []PageInterface
}

// PageInterface ...
type PageInterface interface {
    Title() string
}

// PrintBook ...
func PrintBook(book BookInterface) {
    fmt.Println(book.Title())
}
// package main
package main

import (
    "sandbox/pkg/novel"
    "sandbox/pkg/novelapp"
)

func main() {
    book := novel.NewBook("Book Title", []novel.Page{novel.NewPage("Page Title")})
    novelapp.PrintBook(book)
}
.\main.go:10:20: cannot use book (type *novel.Book) as type novelapp.BookInterface in argument to novelapp.PrintBook:
        *novel.Book does not implement novelapp.BookInterface (wrong type for Pages method)
                have Pages() []novel.Page
                want Pages() []novelapp.PageInterface
1 Like