On Sun, 19 Mar 2017 13:51:05 -0700 (PDT)
aktungmak <aktung...@gmail.com> wrote:

> I am trying to write a function that initializes a generic
> collection. For adding new items to the collection, the user
> specifies a constructor which takes one argument and returns a
> pointer to the struct that will be inserted in the collection, and
> also sets fields to initial values. For example:
> 
> func Constructor(id int) *NewItemX ...
> func Constructor(id int) *NewItemY ...
> func Constructor(id int) *NewItemZ ...
> 
> In the constructor for the collection, I want to accept any function
> which has this general form, although the return type will be
> different for each struct. At first, I thought this might work:
> 
> func NewCollection(itemCtr func(int) interface{}) *Collection ...
> 
> but of course, trying to pass Constructor fails during compilation
> since the types *NewItemX and interface{} do not match:
> 
> .\Collection_test.go:xx: cannot use NewItemX (type func(int)
> *NewItemX) as type func(int) interface {} in argument to NewCollection

I think that's because of [1].

> I could just do this:
> 
> func NewCollection(itemCtr interface{}) *Collection
> 
> but then I would have to do some runtime checks using reflect to make
> sure that it is a func etc and I lose compile-time checking of types.
> 
> How can I express this best in go?

I'd say that your constructor function's type should be defined to
return an interface{} but the actual function should return values of
concrete types -- *NewItemX, *NewItemY etc.

Something like this ([2] on playground):
------------------------------8<------------------------------
package main

type ItemCtor func() interface{}

type Foo struct{}

type FooCollection []*Foo

func ConctructFooCollection(ctor ItemCtor) FooCollection {
        out := make(FooCollection, 10)
        for i := range out {
                out[i] = ctor().(*Foo)
        }
        return out
}

func userProvidedFooPtrCtor() interface{} {
        return &Foo{}
}

func main() {
        _ = ConctructFooCollection(userProvidedFooPtrCtor)
}
------------------------------8<------------------------------

This supposes your collection actually knows the types of its elements.
If it doesn't, we need more context to know, probably.

1. https://golang.org/doc/faq#covariant_types
2. https://play.golang.org/p/l-K5knQCd5

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to