Why does Go allow a struct to implement an unexported interface present in a different package?


I wrote a sample code to understand how the unexported interface works. In the below example, I have declared the unexported repoInterface in the service package.

TestRepo struct in the repo package implements the unexported repoInterface without any issues.

Code structure


// 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/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


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

// Output
// hello

My assumption so far:

This isn’t possible since repo and service
are different packages.

TestRepo struct present in repo package cannot implement the Unexported interface present in the service package.
This is the reason why we export interfaces.

Now I realized that this is not true and my understanding is wrong.


Why does Go allow to implement an unexported interface present in a different package?


service.NewTestService package function requires any value that implements the type interface{ GetName() string }.

repo package exports a type TestRepo which exposes a method GetName() string.

Upon passing the repo.TestRepo to the service.NewTestService function like in service.NewTestService(testRepo), the value implements the interface by providing the expected method set.

All good.

That the type service.repoInterface declares a not exported identifier only discriminates the packages that can use that interface name.

I have reproduced your example on the play https://go.dev/play/p/bp6z2HjwdLS

An interface type declaration containing a not exported identifier is a sealed interface.

Those sealed interfaces can not be implemented by a foreign package.

It can be a not exported method name like in

type Fooer interface {

Try here https://go.dev/play/p/3Syh7R0uS-q

It can also declare a method using a not exported argument type,

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

type sealed int

Answered By – mh-cbon

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.