-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal [WIP]: interface-slices #30391
Comments
One thing that will work in some situations is to push the interface definition up a level. If you want a list of things that can be converted to strings: type StringList interface {
// String returns the n'th string.
String(n int) string
} This can be trivially implemented by FWIW, on the one occasion that I've really wanted to convert a slice of a concrete type to a slice of an interface type, I ended up using reflection. These two approaches (push the list-ness into the interface, or use reflection) are also embodied by |
Note that the current proposals for generics do not require templated code for each instance either. Templated code is an implementation strategy; are there semantic differences between this an generic containers? |
I'm not sure. I periodically conclude that it's clearly equivalent to a generic container (with some restrictions on the generic type), and at other times conclude that it's definitely not. I feel like the interface boxing/unboxing is a significant difference from generic code, but I'm not sure it's actually useful for anything if generics are available. On the other hand, this would solve many of the things for which I have wanted generics, without requiring nearly the generalized complexity of generics. |
Why not enhance the built in |
I don't think that would actually cover this use case at all, because that would create an array of pointers. A big part of the goal here is to get away from the huge number of pointers that end up being needed for slices of interfaces. |
Thanks for the suggestion. I agree with @bcmills that a generics proposal ought to address the same issues being described here: the ability to work with a slice of some generically specified type. I'm going to close this proposal in the hopes that we will adopt some form of generics. If we decide against that, we can revisit this. |
(See some similarities with #26056)
What version of Go are you using (
go version
)?N/A
Does this issue reproduce with the latest release?
N/A
What operating system and processor architecture are you using (
go env
)?N/A
What did you do?
Wanted to write code using slices of possibly-unknown types, efficiently.
What did you expect to see?
A way to get some of the utility of interfaces, without the massive allocator overhead.
What did you see instead?
If you have a slice of things which satisfy an interface, and you want a slice of that interface, you have to manually rebox the items. A slice of 1M interfaces contains 1M pointers. This is horrible.
What I don't have: any idea how to produce a workable/clean syntax.
What I do have: A description of a thing that I think would be very useful for developers confronted with this.
The basic concept: An interface-slice type, which is distinct from a slice-of-interfaces. An interface-slice is assignable from a slice of objects which satisfy its interface. There is implicit boxing/unboxing involved, but instead of boxing/unboxing each item to create the slice, boxing/unboxing happens only at the time when you're trying to access an item.
So, for instance:
Why do I think this would be useful? Because code that deals with large numbers of objects, which might be of multiple types, is currently allocating millions of interfaces. In many cases, it would be adequately served by a handful of interface-slices wrapping slices of the underlying concrete objects. If the interfaces were being used only for brief inner loops, many of them might never escape to the heap, and thus, not require allocation at all.
The best we can do right now is to use
interface{}
, and type assertions. You can do okay with this, but you lose all the documentary power of being able to specify that, rather than any arbitrary object, you are looking only for (1) slices, of (2) things that satisfy a particular interface. You also can't handle a new arbitrary item which satisfies your interface. For instance, consider what would happen if you tried to do this for Stringer; how do you check your interface{} against every type that implements Stringer without complex and expensivereflect
checks? If you could instead get a slice known to be a slice of things implementing Stringer, and could iterate through it as if it were a slice of Stringer interfaces, life would be better.I don't have a good handle of a syntax for this.
interface[]{}
almost works, but it can't be used for a named interface type. If this were just added as a new rule for []Interface (permitting assignments from compatible-ish slices), it would probably impose costs on any and all code using []Interface already, and possibly introduce very strange bugs. So I'm completely stumped on syntax.This doesn't seem to be quite the same case as generics; the goal isn't to generate templated code for each specific instance of a slice satisfying the interface, but to have runtime interface-handling code which better handles the fairly common case of slices of a concrete type.
The text was updated successfully, but these errors were encountered: