How to solve "interface method must have no type parameters"? [duplicate]
Asked Answered
S

1

15

I'm trying out go generics in 1.18beta2 and I'm trying to write an abstraction layer for key/value store, boltdb. This is what I'm trying to achieve with it.

type Reader interface {
    Read(bucket []byte, k ...[]byte) ([][]byte, error)
    ReadDoc[V Unmarshaler](bucket []byte, factory func() (V, error), k ...[]byte) ([]V, error)
}

type Unmarshaler interface {
    UnmarshalKV(v []byte) error
}

So that I can provide it a factory to create the type when it finds a key/value, unmarshal the data into it and return back a slice of that specific type. Only I get "interface method must have no type parameters" from the compiler. Why are't type parameters allowed in interfaces? Is supporting this planned? This has crushed my dreams... Would have been perfect. It does however work out of interface.

Stubborn answered 15/2, 2022 at 19:15 Comment(3)
Possibly related: #70668736.Litta
Would the following suffice for what you are trying to achieve? go.dev/play/p/nu6gIJRh5fV?v=gotipLitta
Not sure. I haven't seen that before. A usage example of the method would: MyTestDocs, err := boltdb.ReadDoc([]byte("bucket"), NewTestDocument, []byte("key1"), []byte("key2") where the implementer of the interface is the databaseStubborn
B
13

Ran into the same issue earlier today. This seems to be a design decision for the generics/type parameters since there could be multiple "ways" of interpreting a method with type parameters in interface definition (and implementation work).

In some cases it could either mean:

  • Identity of the argument is not preserved.
  • Need to traverse the whole tree at compile time, which impacts performance.
  • Need for reflection at runtime, which impacts performance.
  • Parametrized method do not implement interfaces, which would lead to confusion.

More information in the Type parameters proposal, No parametrized methods

You could however move the type parameter into the interface type definition. Proposal, Very high level overview:

type Reader[V Unmarshaler] interface {
    Read(bucket []byte, k ...[]byte) ([][]byte, error)
    ReadDoc(bucket []byte, factory func() (V, error), k ...[]byte) ([]V, error)
}

type Unmarshaler interface {
    UnmarshalKV(v []byte) error
}
Brigitta answered 15/2, 2022 at 19:28 Comment(2)
This is what I had to change it to... which is not ideal.. at all. go.dev/play/p/ryWl3sf4KyJ?v=gotip but it works... I'm probably better off writing a callback to do the work and append to a slice outside the function...Stubborn
Actually, now that I think about it. This might be better for my use case because I'd use all those methods in my services when accessing a repository. So I can just write Reader[*MyType] when I need to access them. I could also shorten it so I dont need a factory every time. go.dev/play/p/YgcWZAP8vhb?v=gotip I will accept this as the answer. Thanks for your help baywet, @LittaStubborn

© 2022 - 2024 — McMap. All rights reserved.