Skip to content

proposal: Derive interface type from a concrete type #23886

Closed
@guangda-hu

Description

@guangda-hu

I'm not sure if this is a good idea. But I have thought about it several times and would like to share it in case it has not been considered. This is for future versions of Go (probably Go 2.0).

Proposal

It would be nice if there is a way to define an interface type that is the method set of some arbitrary type T. My proposal is to simply generalize the existing interface embedding:

interface {
  T
}

Currently T can only be an interface. The proposal is to allow other types as well, and the interface contains the method sets of all embedded types.

  • The same restrictions of struct embedding applies: T must not be a pointer type, and for non-interface type, *T can also be embeded.
  • The rules of interface embedding also applies: the method sets of embedded types must be disjoint.

Application

Suppose I need to write the following function that uses a concrete type someservice.Client:

func MyFunc(*someservice.Client) {
 // ....
}

To write unit test for MyFunc, I want to fake someservice.Client. An easy way is to change the above code to

type myInterface interface {
  // all methods needed
}
var _ myInterface = &someservice.Client{}
func MyFunc(myInterface) {
}

Here myInterface contains a subset of the method set of *someservice.Client. However, if the method set is large, and if I need to change code back and forth (so it's hard to determine which methods are used), it would be tedious to keep myInterface up to date. The proposal will solve the problem:

type myInterface interface {
  *someservice.Client
}

Note 1

A google search shows that people have written tools to generate interface from struct: https://github.com/vburenin/ifacemaker (not necessarily to solve the same problem I mentioned though).

Note2

Another note is that I think this can somewhat make "polymorphism" easier in Go. Struct embedding is like "inherence" in many ways, but not always. Suppose we have

type Derived struct {
  Base
}

We still need an interface type that contains the methods of Base if we want something that can hold either a Base or a Derived. And the proposed interface { Base } is such an interface.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions