嵌套接口:X不实现Y(Z方法的类型错误)

时间:2018-01-27 11:52:51

标签: go interface

在一个包中,我有一个接口Repository,它有一个返回接口GetReporter的方法Reporter。这由Execute函数使用,该函数使用Repository并通过Reporter函数获取其GetReporter

在另一个包中,我有一个结构GithubRepository,其方法GetReporter返回GithubReporter

在第三个包中,我想使用Execute实例从包#1中调用GithubRepository函数。

我试图使包1和包2彼此独立,没有一个从另一个导入的东西。第三个包应该结合前两个。

Golang回归:

cannot use githubRepository (type GithubRepository) as type Repository in argument to Execute:
    GithubRepository does not implement Repository (wrong type for GetReporter method)
        have GetReporter(string) GithubReporter
        want GetReporter(string) Reporter

代码:

package main

// Package #1

type Repository interface {
  GetReporter(string) Reporter
}

type Reporter interface {
  ChangeStatus(string) error
}

func Execute(r Repository) {
  // Do something with the repository
}

// Package #2

type GithubRepository struct {
}

type GithubReporter struct {
}

func (repo *GithubRepository) GetReporter(sha string) GithubReporter {
 return GithubReporter{}
}

func (reporter *GithubReporter) ChangeStatus(status string) error {
  // Change the status
  return nil
}

// Package #3

func main() {
  githubRepository := GithubRepository{}
  Execute(githubRepository)
}

去游乐场:https://play.golang.org/p/ph0sZnyAC5I

2 个答案:

答案 0 :(得分:2)

在这种情况下,不可能使两个包独立。但是,使用go1.9及其类型别名,可以这样做。

首先,正如谚语所说,A little copy is better than a little dependency。您应该将Reporter的定义部分复制到包B,并根据它更改签名:func (repo GithubRepository) GetReporter(sha string) Reporter

然而,编译器不理解这两个接口是一样的。但是在type alias的帮助下,它可以解决。将定义type Reporter interface {...}更改为type Reporter = interface {...}。它现在将编译。

答案 1 :(得分:0)

使用GithubRepositoryGithubReporter作为值接收器,因为您没有将变量创建为指针。并在方法GetReporter

中返回接口
func (repo GithubRepository) GetReporter(sha string) Reporter {
 return GithubReporter{}
}

func (reporter GithubReporter) ChangeStatus(status string) error {
  // Change the status
  return nil
}

希望这会有所帮助。

请参阅操作:https://play.golang.org/p/Gugm3LetqHU

如果你在不同的包中有接口,这些就不需要做特殊的事情了,只需指向那个包的接口。

在包A中

package A

type Repository interface {
    GetReporter(string) Reporter
}

type Reporter interface {
    ChangeStatus(string) error
}

func Execute(r Repository) {
    r.GetReporter("report:r").ChangeStatus("status:s")
}

在包B中

package B

import (
    "fmt"
    "test/A"
)

type GithubRepository struct {
}

type GithubReporter struct {
}

func (repo GithubRepository) GetReporter(sha string) A.Reporter {
    fmt.Println(sha)
    return GithubReporter{}
}

func (reporter GithubReporter) ChangeStatus(status string) error {
    // Change the status
    fmt.Printf(status)
    return nil
}

您可以尝试Import Dot