4

I have two interfaces, A and B. It happens that A includes B. Finally, I have a concrete implementation of A (call it Impl), which, by definition, also implements B.

For example:

type A interface {
    Close() error
    Read(b []byte) (int, error)
}

type Impl struct {}
func (I Impl) Read(b []byte) (int, error) {
    fmt.Println("In read!")
    return 10, nil
}
func (I Impl) Close() error {
    fmt.Println("I am here!")
    return nil
}

Since A requires Read(), and Impl implements A, it also satisfies io.Reader.

If I try to pass individual items across functions, it works fine. But if I try slices of A to functions expecting io.Reader, it fails.

Example:

func single(r io.Reader) {
    fmt.Println("in single")
}
func slice(r []io.Reader) {
    fmt.Println("in slice")
}
im := &Impl{}

// works
single(im)

// FAILS!
list := []A{t}
slice(list)

If I can pass an A to single(r io.Reader), why can I not pass []A to slice(r []io.Reader), and how would I correct it?

Actual implementation at https://play.golang.org/p/QOREQJTQhD just uncomment the last two lines in main() and the error shows:

main.go:38: cannot use list (type []A) as type []io.Reader in argument to slice
deitch
  • 14,019
  • 14
  • 68
  • 96

1 Answers1

3

I kind of asked something similar here In Go, how can I make a generic function with slices?

Sadly, this is definitely a weakness in Go. The only way for you to go around this is to make a new slice of type []io.Reader with elements from []A

Community
  • 1
  • 1
Thomas
  • 8,306
  • 8
  • 53
  • 92
  • Thanks @Thomas. I came across your question when I was trying to figure this out, but wondered if it is the same thing. I am not looking for generics (although you could argue that my `A` and `io.Reader` are just specialized cases of your `interface` generic), but rather to pass in `[]A` (whose implementations must implement `io.Reader`) to a function that expects `[]io.Reader`. I can pass `A` to a function that expects `io.Reader`, so why not the slice as well? – deitch Nov 25 '16 at 13:46
  • @deitch from my understanding of Go, a slice is a very special case. You can do a.(io.Reader) but not []a.([]io.Reader), they are unconvertible and Go is strongly typed – Thomas Nov 25 '16 at 16:32
  • Reading through your other question, and the one flagged above, I was able to understand it. But you are right, and @icza is wrong in that (a) this isn't an exact duplicate (it has the same underlying principles, but not exactly the same question) and (b) this most certainly *is* a weakness. – deitch Nov 26 '16 at 16:05
  • I think the -1 is hateful and should really be given to people who don't put effort in writing their question, etc. I have upvoted you to balance for that – Thomas Nov 26 '16 at 17:27
  • Thanks @Thomas, but most especially appreciate your help. – deitch Nov 26 '16 at 21:07