Skip to content

proposal: spec: allow selective method embedding for interface definitions (like TypeScript's Pick) #73373

Closed as not planned
@rarick

Description

@rarick

Go Programming Experience

Intermediate

Other Languages Experience

No response

Related Idea

  • Has this idea, or one like it, been proposed before?
  • Does this affect error handling?
  • Is this about generics?
  • Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit

Has this idea, or one like it, been proposed before?

No - I was unable to find related proposals. I would expect there to be existing proposals, but was unable to find any. Please link if I am mistaken, I'd be interested in reading discussion around this.

Does this affect error handling?

No

Is this about generics?

No

Proposal

Background:
Effective Go encourages the use of defining small, consumer-oriented interfaces. In practice, this results in some toil in copying signatures as well as importing the necessary paths to correctly define those signatures.

For example:

// `github.com/some/go/library`
import (
    transitive "github.com/some/transitive/dependency"
)

type Client struct {}

(c *Client) Put(ctx context.context, input *transitive.Input, ...func(*transitive.Options)) (*transitive.Output, error) {
  ...
}

Now a consumer-defined interface must match this declaration and imports:

// `github.com/some/limplementer`
import (
    "github.com/some/go/library"
    transitive "github.com/some/transitive/dependency"
)

type Putter interface {
    Put(ctx context.context, input *transitive.Input, ...func(*transitive.Options)) (*transitive.Output, error)
}

While not a large amount of toil, the developer's goal will very frequently be to declare the exact same signature from some type, so there is some opportunity to simplify this.

Proposal:
Introduce syntax for consumer-side interfaces to selectively include methods from existing interfaces or types (similar to TypeScript's Pick), e.g.:

type ConsumerInterface interface {
    io.ReadCloser.Read
    (*os.File).Write
}

This allows defining ConsumerInterface with just the Read method from io.ReadCloser and Write from *os.File.

Pros:

  • Further encourages interface usage by reducing friction
  • Reduces boilerplate
  • Improves readability for consumer-defined APIs

Drawbacks:

  • Increases language complexity
  • Less "WYSIWYG"
  • Can obscure interface method sources
    • Especially in the case where selections may propagate across
  • May complicate tooling (e.g., go doc, gopls)
  • May encourage bad interface definition

Language Spec Changes

No response

Informal Change

No response

Is this change backward compatible?

Yes

Orthogonality: How does this change interact or overlap with existing features?

Go currently allows for the composition of interface types through interface embedding:

// package `io`
type ReadCloser interface {
	Reader
	Closer
}

This proposal is similarly for the composition of an interface, but through selective embedding.

Would this change make Go easier or harder to learn, and why?

Yes. It is another feature and a new way to compose an interface.

Cost Description

  • Increases language complexity
  • Less "WYSIWYG"
  • Can obscure interface method sources
    • Especially in the case where selections may propagate across
  • May complicate tooling (e.g., go doc, gopls)
  • May encourage bad interface definition

Changes to Go ToolChain

No response

Performance Costs

No response

Prototype

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    LanguageChangeSuggested changes to the Go languageLanguageChangeReviewDiscussed by language change review committeeLanguageProposalIssues describing a requested change to the Go language specification.Proposal

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions