4 ms·
type Abstract interface { value() string } type Impl struct { str string } func (impl Impl) value() string { return im
by jwalton 5y ago
type Abstract interface {
value() string
}
type Impl struct {
str string
}
func (impl Impl) value() string {
return impl.str
}
func ShowAbstracts(arr []Abstract) {
for _, a := range arr {
fmt.Println(a.value())
}
}
func main() {
arr := []Impl{Impl{"a"}, Impl{"b"}}
ShowAbstracts(arr) // This doesn't work, because arr is []Impl, not []Abstract
}
It works with `arr := []Abstract{Impl{"a"}, ...}` of course, but if you already have a 100K slice of Impl, you'd have to copy all 100K elements into a slice of Abstract to call ShowAbstracts in this example.
- marcus_holmes 5y agoThanks for the explanation :) Slices are backed by arrays, not actual arrays - copying a 100K slice into another slice isn't as intensive as it sounds. I'm not sure I see this as "interfaces are broken in Go", or something that requires generics to solve? (I do realise that the language itself uses generics to implement the copy keyword for this).
- jwalton 5y agoUnfortunately I think copying 100K elements is going to be exactly as painful as it sounds. The `[]Impl` is going to be (more or less) an array of 100K strings. The `[]Abstract` will be an array of interfaces, each of which is internally two pointers, so I'll have to allocate 1.6M of RAM and fill that RAM with pointers in order to convert a `[]Impl` into a `[]Abstract`. Generics fix this handily, because I can write: func ShowAbstracts[T Abstract](arr []T) { for _, a := range arr { fmt.Println(a.value()) } } And now when I try to pass in my `[]Impl`, Go will compile a new `ShowAbstracts(arr []Impl)` transparently behind the scenes.
- _flux 5y agoI wouldn't call it broken duck typing. The problem is that ShowAbstracts could just modify the array and put an instance of Abstract there that _isn't_ an Impl, thus violating the original constraint of arr containing only instances of Impl. Once again mutability/invariance raises its ugly head!
- jwalton 5y agoThat is a very good point.