You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
spec: add generic programming using type parameters #43651
We propose adding support for type parameters to Go. This will change the Go language to support a form of generic programming.
A detailed proposal document has been published, with input from many members of the Go community. We are now taking the next step and proposing that this document become a part of the language.
A very high level overview of the proposed changes:
Functions can have an additional type parameter list that uses square brackets but otherwise looks like an ordinary parameter list: func F[T any](p T) { ... }.
These type parameters can be used by the regular parameters and in the function body.
Types can also have a type parameter list: type MySlice[T any] []T.
Each type parameter has a type constraint, just as each ordinary parameter has a type: func F[T Constraint](p T) { ... }.
Type constraints are interface types.
The new predeclared name any is a type constraint that permits any type.
Interface types used as type constraints can have a list of predeclared types; only type arguments that match one of those types satisfy the constraint.
Generic functions may only use operations permitted by their type constraints.
Using a generic function or type requires passing type arguments.
Type inference permits omitting the type arguments of a function call in common cases.
In the discussion on this issue, we invite substantive criticisms and comments, but please try to avoid repeating earlier comments, and please try to avoid simple plus-one and minus-one comments. Instead, add thumbs-up/thumbs-down emoji reactions to comments with which you agree or disagree, or to the proposal as a whole.
If you don't understand parts of the design please consider asking questions in a forum, rather than on this issue, to keep the discussion here more focused. See https://golang.org/wiki/Questions.
an interface{} wouldn't make sense here since we're describing a generic trait that needs to be implemented. This is more meta-code and interface{} is still concrete - even if it is "generic" in some senses of the word.
I'm also having trouble thinking how you could implement any interface{} generic parameters, since you don't know what the interface will actually be - and if you're doing interface type-checking here, it's defeating the entire point of generics (IMO).
Reacted by Jian Li, Miguel Jimeno, Michael Wilner, Didip Kerabat, Nicholas Carey, qaisjp, Alexey Shatunov, Sascha Matzke, Robert, André and 81 more
Reacted by Tom Thorogood, Awad Diar, Robert Pająk, ngortheone, adwhit, Peng Gao, Mozzi, grantseltzer, Noah Muldavin and inliquid
Reacted by Awad Diar, Mehdi Hasan Khan, dgb23, Branden J Brown, Pascal S. de Kloe, Tom Thorogood, Dorian Thiessen, baxiry and Martin von Gagern
I remain concerned that this proposal overloads words (and keywords!) that formerly had very clear meanings — specifically the words type and interface and their corresponding keywords — such that they each now refer to two mostly-distinct concepts that really ought to instead have their own names. (I wrote up this concern in much more detail last summer, at https://github.com/bcmills/go2go/blob/master/typelist.md.)
Specifically, the word type today is defined as:
A type determines a set of values together with operations and methods specific to those values.
Under this proposal, I believe that a type would instead be either a set of values with operations, or a set of sets of values, each with its own set of operations.
And today the word interface, in the context of Go, refers to a type, such that:
A variable of interface type can store a value of any type with a method set that is any superset of the interface.
Under this proposal, a variable of interface type can store a value of any type with a method set that is any superset of the interface, unless that interface type refers to a set of sets of values, in which case no such variable can be declared.
I'd like to see more detail on the exact wording proposed for the spec, but for now I am against this specific design, on the grounds that the ad-hoc overloading of terms is both confusing, and avoidable with relatively small changes in syntax and specification.
Reacted by Lars Walen, Rajender Reddy Kompally, Thor, Jon Nials, dgb23, Adrian Price, Cameron Elliott, Pierce Lally, Jeremy Loy, pugnack and 130 more
Reacted by Reto, Josh Leverette, Mehdi Hasan Khan, pteromyscus, Christopher Nelson, David Adams, Brendan O'Brien, Rob Prentiss, Arman Ordookhani, Christopher Probst-Ranly and 14 more
Reacted by Sean Liao, Mehdi Hasan Khan, Dave Vasilevsky, qaisjp, DeedleFake, Christopher Probst-Ranly, Stan B. and digiter
Reacted by Andreas Bergmeier, Joseph Boudou and J. Emrys Landivar
Reacted by Matt Layher, Luke Champine, Alexey Shatunov, Didier Spezia, Jannis Rieger, Nathaniel Wheeler, Geon Kim, jkmpariab, Mauricio Lopes, GalvinGao and 3 more
The difference are very subtil. How will you document the best practice when a Go1 interface is enough ?
I mean, how to prevent abuse of generic when both can be used ?
Reacted by Lars Walen, Scott Reisor, Rajender Reddy Kompally, Kevin Dang, Thor, Edward Minnix III, Jon Nials, Michael Rybka, Jeff Sumler, rittneje and 213 more
Reacted by Bryan C. Mills, Petr, Alexey Shatunov, Didier Spezia, Julian V. Modesto, hakihet, Lee Jacobs, Leo Goodstadt, mishudark, Bloom and 8 more
Reacted by Will Noble
Reacted by Rajender Reddy Kompally, Kenan Kessler, Mehdi Hasan Khan, Thor, Sascha Matzke, Christopher Probst-Ranly, hbc, Pedro Silva, Vittorio Camisa and myBella
Reacted by Mateusz Czapliński, Christopher Probst-Ranly, Paulo, Chapman Ou, Felipe Romani, Patryk Rogalski, Jarvis Chu , Dino Omanovic and Mike McDermott
Would still prefer to have the empty interface. How tedious can this really be? Especially since we can define type aliases ourselves...
I think interface{} is a mistake. It is a hack to permit something like void * without any semantic cues to help a user understand what is going on. I would have preferred to have "any" as a type in the language from the beginning, even it it was just an alias for interface{} under the covers.
Of course, the new "any" is different than interface{}. It would be nice to have a named type that means "any type by reference" instead of "any type by substitution".
Reacted by pteromyscus, David Adams, Michael Wilner, Jeremy Loy, Didip Kerabat, Christopher Probst-Ranly, elijahdorman, Andreas Bergmeier, Kat Mitchell, Zhu Chu and 50 more
Reacted by Awad Diar, fzipp, Torsten Bronger, bokwoon95, Jamie Hall, Tom Thorogood, Ciaran Liedeman, Nikita Mochalov, Matt Mc, dchapes and 12 more
The difference are very subtil. How will you document the best practice when a Go1 interface is enough ?
I mean, how to prevent abuse of generic when both can be used ?
Valid point, in your example, an interface would be the better choice. However, a more apt use case of generics would be sort. Operations on slices of arbitrary types would be distinctly less verbose with generics as compared to interfaces. This talk touches on some of the points: blog.golang.org/why-generics (disclaimer: syntax in this link is different than this generics proposal, but the points are useful to draw comparison)
Reacted by Maciej Płachta, Phil, baxiry, Alex Besogonov, Miroslav Kravec, artti-jaakkola, Peng Gao, Grégoire Geis, Paulo Villela, Rene Vallecillo V and 3 more
What are the plans for amending the standard library to utilize generics? I see two important tracts of work here.
retroactively applying generics to packages like sort, container/list
Creating new packages and libraries that were previously cumbersome without generics; i.e. mathematical set functions,
Reacted by Adrian Price, Anchit Bajaj, Diogo Pinela, Didip Kerabat, deef, DeedleFake, qaisjp, Rajender Reddy Kompally, Mateusz Czapliński, Jason Connell and 163 more
Reacted by Bart Pelle, Michael Mattheakis, Radoslav Gerganov, Marc Brooks, David Turner and Andrii Cherpatiuk
A type determines a set of values together with operations and methods specific to those values.
That sentence describes a struct. An interface is also a kind of type in Go, and it does not determine the set of values or operations that are present, only the set of methods.
The fact that a type is not just a struct is why the syntax in the language is type foo interface { ... }, type foo struct { ... }, and even type foo bar or type foo = bar.
A generic type is just as concretely a set of values, operations, and methods as an interface is (which is to say, you an argue that it isn't). So either we should redefine interface to not be a type (by the definition you're quoting), or we should accept that a generic type is also a type, just one that requires type parameters to be resolved before it becomes a concrete type.
If the proposal is misusing the term "type" in place of "type parameter" anywhere, I think that could be valid criticism... but it sounds like you're criticizing some ambiguous/arguably wrong terminology that exists in the Go language spec, which is terminology that is refuted by the language itself, as demonstrated by Go syntax above. If an interface is not a type, we should not prefix the declaration with the word type, but we do.
That whole area of discussion seems off topic here, and clarifications to the existing language spec could be proposed somewhere else? I've read through the generic proposal several times and I haven't come away feeling like the terminology used was ambiguous or confusing, and your statements here do not effectively make the case for that either, in my opinion.
Reacted by Phil Mansfield, DeedleFake, Jeff Sumler, baldrich-randori, Chris Reeves, sztanpet, Roman, johanfo, Eric Miller, hakihet and 35 more
Reacted by Axel Wagner, Bryan C. Mills, Patrick Baxter, Tv, Jonah, Aram Hăvărneanu, Samuel Kelemen, Borgstrom ♔, antichris, adwhit and 1 more
Of course, the new "any" is different than interface{}.
The new "any" is not different from interface{} as a type constraint. [T any] and [T interface{}] are interchangeable as per the proposal.
Reacted by qaisjp, Awad Diar, baldrich-randori, Didier Spezia, Dominik Honnef, Dominik Schulz, Xavier-Frédéric Moulet, Dave Vasilevsky, Maciej Płachta, Brandon Bennett and 35 more
No change in consensus, so accepted. 🎉
This issue now tracks the work of implementing the proposal.
— rsc for the proposal review group
That is our usual way of using issues, but this issue continues to gather comments that are not relevant to tracking the work of implementing the proposal. Honestly, that was probably inevitable and understandable. But it's no longer the place for comments and questions about the proposal itself.
I'm going to lock this issue and close it. We won't forget about the implementation without a tracking issue, I promise.
Activity
atdiar commentedon Jan 12, 2021
ALTree commentedon Jan 12, 2021
atdiar commentedon Jan 12, 2021
hanneshayashi commentedon Jan 12, 2021
tsal commentedon Jan 12, 2021
an
interface{}wouldn't make sense here since we're describing a generic trait that needs to be implemented. This is more meta-code andinterface{}is still concrete - even if it is "generic" in some senses of the word.I'm also having trouble thinking how you could implement any
interface{}generic parameters, since you don't know what the interface will actually be - and if you're doing interface type-checking here, it's defeating the entire point of generics (IMO).coder543 commentedon Jan 12, 2021
bcmills commentedon Jan 12, 2021
I remain concerned that this proposal overloads words (and keywords!) that formerly had very clear meanings — specifically the words type and interface and their corresponding keywords — such that they each now refer to two mostly-distinct concepts that really ought to instead have their own names. (I wrote up this concern in much more detail last summer, at https://github.com/bcmills/go2go/blob/master/typelist.md.)
Specifically, the word type today is defined as:
Under this proposal, I believe that a type would instead be either a set of values with operations, or a set of sets of values, each with its own set of operations.
And today the word interface, in the context of Go, refers to a type, such that:
Under this proposal, a variable of interface type can store a value of any type with a method set that is any superset of the interface, unless that interface type refers to a set of sets of values, in which case no such variable can be declared.
I'd like to see more detail on the exact wording proposed for the spec, but for now I am against this specific design, on the grounds that the ad-hoc overloading of terms is both confusing, and avoidable with relatively small changes in syntax and specification.
flibustenet commentedon Jan 12, 2021
The difference are very subtil. How will you document the best practice when a Go1 interface is enough ?
I mean, how to prevent abuse of generic when both can be used ?
nadiasvertex commentedon Jan 12, 2021
I think interface{} is a mistake. It is a hack to permit something like void * without any semantic cues to help a user understand what is going on. I would have preferred to have "any" as a type in the language from the beginning, even it it was just an alias for interface{} under the covers.
Of course, the new "any" is different than interface{}. It would be nice to have a named type that means "any type by reference" instead of "any type by substitution".
michaelwilner commentedon Jan 12, 2021
Valid point, in your example, an interface would be the better choice. However, a more apt use case of generics would be
sort. Operations on slices of arbitrary types would be distinctly less verbose with generics as compared to interfaces. This talk touches on some of the points: blog.golang.org/why-generics (disclaimer: syntax in this link is different than this generics proposal, but the points are useful to draw comparison)JeremyLoy commentedon Jan 12, 2021
What are the plans for amending the standard library to utilize generics? I see two important tracts of work here.
sort,container/listcoder543 commentedon Jan 12, 2021
@bcmills
That sentence describes a struct. An interface is also a kind of type in Go, and it does not determine the set of values or operations that are present, only the set of methods.
The fact that a type is not just a struct is why the syntax in the language is
type foo interface { ... },type foo struct { ... }, and eventype foo barortype foo = bar.A generic type is just as concretely a set of values, operations, and methods as an interface is (which is to say, you an argue that it isn't). So either we should redefine interface to not be a type (by the definition you're quoting), or we should accept that a generic type is also a type, just one that requires type parameters to be resolved before it becomes a concrete type.
If the proposal is misusing the term "type" in place of "type parameter" anywhere, I think that could be valid criticism... but it sounds like you're criticizing some ambiguous/arguably wrong terminology that exists in the Go language spec, which is terminology that is refuted by the language itself, as demonstrated by Go syntax above. If an interface is not a type, we should not prefix the declaration with the word
type, but we do.That whole area of discussion seems off topic here, and clarifications to the existing language spec could be proposed somewhere else? I've read through the generic proposal several times and I haven't come away feeling like the terminology used was ambiguous or confusing, and your statements here do not effectively make the case for that either, in my opinion.
fzipp commentedon Jan 12, 2021
The new "any" is not different from interface{} as a type constraint.
[T any]and[T interface{}]are interchangeable as per the proposal.440 remaining items
m-ivanov commentedon Feb 20, 2021
billinghamj commentedon Feb 20, 2021
GoldsteinE commentedon Feb 20, 2021
rsc commentedon Feb 20, 2021
In #43651 (comment) I wrote
That is our usual way of using issues, but this issue continues to gather comments that are not relevant to tracking the work of implementing the proposal. Honestly, that was probably inevitable and understandable. But it's no longer the place for comments and questions about the proposal itself.
I'm going to lock this issue and close it. We won't forget about the implementation without a tracking issue, I promise.
gopherbot commentedon Mar 19, 2021
Change https://golang.org/cl/303389 mentions this issue:
design: promote type parameters to a proposalgopherbot commentedon Apr 1, 2021
Change https://golang.org/cl/306689 mentions this issue:
design: update type parameters design for type setsgopherbot commentedon Aug 20, 2021
Change https://golang.org/cl/343732 mentions this issue:
cmd/compile: enable -G=3 by default