Description
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