0

我写了一个示例代码来了解未导出的 接口是如何工作的。在下面的示例中,我在服务包中声明了未导出的repoInterface 。

repo包中的TestRepo结构实现未导出的 repoInterface,没有任何问题。

Code structure
repo
  repo.go
service
  service.go
main.go

服务.go

// service/service.go

// this is the interface which the TestRepo struct implements in repo package
type repoInterface interface{
    GetName() string
}

type TestService struct{
    repo repoInterface
}

func NewTestService(r repoInterface) TestService {
    return TestService{
       repo: r,
    }
}

func (s TestService) GetName() string {
    return s.repo.GetName()
}

回购/repo.go

// repo/repo.go
type TestRepo struct{
    name string
}

func NewTestRepo(name string) TestRepo {
    return TestRepo{
        name: name,
    }
}

// implements repoInterface present in service package
func (r TestRepo) GetName() string {
    return r.name
}

main.go

func main() {
    testRepo := repo.NewTestRepo("hello")
    testService := service.NewTestService(testRepo)
    fmt.Println(testService.GetName())
}

// Output
// hello

到目前为止我的假设:

这是不可能的,因为 repo 和 service 是不同的包。

repo 包中存在的 TestRepo 结构无法实现服务包中存在的 Unexported 接口。这就是我们导出接口的原因。

现在我意识到这不是真的,我的理解是错误的。

问题:

为什么 Go 允许实现存在于不同包中的未导出接口?

4

1 回答 1

1

service.NewTestServicepackage 函数需要任何实现type interface{ GetName() string }的值。

repo导出一个公开方法的类型TestRepoGetName() string

在将 传递repo.TestReposervice.NewTestService类似 in 的函数时service.NewTestService(testRepo),该值通过提供预期的方法集来实现接口。

都好。

该类型service.repoInterface 声明一个未导出的标识符仅区分可以使用该接口名称的包。

我已经在剧中复制了你的例子https://go.dev/play/p/bp6z2HjwdLS


包含未导出标识符的接口类型声明是密封接口。

那些密封的接口是不能用外来的包来实现的。

它可以是未导出的方法名称,如

type Fooer interface {
    Foo() 
    sealed()
}

在这里试试https://go.dev/play/p/3Syh7R0uS-q

它还可以使用未导出的参数类型声明方法,


type Foo interface {
    GetName() string
    GetName2() sealed
}

type sealed int
于 2022-02-21T20:42:51.020 回答