FAQ
Let's say you want to create some generic collection manager that keeps a
cache of some remote objects of different types which are supplied through
some king of a sourcer object that always returns a collection of different
things depending on the method called on it. A probably horrible
implementation of such thing is in below. Specifically, the register method
and all the conversions between B and C to IA smells bad. It is important
to note that the CollectionManager needs a few common set of properties on
all the types to do the generic things that it does but below I just assume
id and a Get() method in here but in practice, it needs some other
properties and it does more complex generic things on the its objects than
just a Get().

In OO world, you define a base class and work with that. Embedded types
does not work here too. How do I design/do such thing with GO?

func main() {

     s := NewSourcer(...) //Not in blew

     bManager := NewCollectionManager(s)

     bManager.Register(func(s *Sourcer) []IA {

         results = s.GetAll_B() //returns []B

         newResults := make([]IA, len(results))

             for i, res := range results {

                 newResults[i] = IA(res)

             }

         return newResults

     })

     cManager := NewCollectionManager(s)

     cManager.Register(func(s *Sourcer) []IA {

         results = s.GetAll_C() //returns []C

         newResults := make([]IA, len(results))

             for i, res := range results {

                 newResults[i] = IA(res)

             }

         return newResults

     })

     w := bManager.Update()

     k := cManager.Update()


     x := bManager.Get("foo").(B)

     y := cManager.Get("bar").(C)

}


type IA interface {

     ID() string

}

type B struct {

     id string

     z string

     ...

}

func (b B) ID() string {

     return b.id

}

type C struct {

     id string

     w int

     ...

}


func (c C) ID() string {

     return c.id

}


type CollectionManager struct {

     s *Sourcer

     all map[string]IA

     gf func(s *Sourcer) []IA

}


func NewCollectionManager(s *Sourcer) *CollectionManager {

    cm = &CollectionManager{

         s: s,

     }

     return cm

}


func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

     gf = f

}


func (c *CollectionManager) Update() {

     res := f(c.s)

     for i := range res {

        id = res[i].ID()

        all[id] = res[i]

     }

}

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Egon at Dec 31, 2014 at 1:14 pm

    On Wednesday, 31 December 2014 12:34:02 UTC+2, Mike wrote:
    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it. A probably horrible
    implementation of such thing is in below. Specifically, the register method
    and all the conversions between B and C to IA smells bad. It is important
    to note that the CollectionManager needs a few common set of properties on
    all the types to do the generic things that it does but below I just assume
    id and a Get() method in here but in practice, it needs some other
    properties and it does more complex generic things on the its objects than
    just a Get().
    Please try to give the full context for the problem
    (https://github.com/golang/go/wiki/HowToAsk). I.e. how are you going to use
    that code, how does it help people etc... Without that information it's
    hard to actually understand what is the real world problem being solved. To
    me the existance of such collection manager already is questionable design
    decision - not saying it's wrong, just it isn't goish approach (and given
    the full real-world problem might make sense).

    As a first (guess), don't write the generic collection manager.

    + Egon


    In OO world, you define a base class and work with that. Embedded types
    does not work here too. How do I design/do such thing with GO?

    func main() {

    s := NewSourcer(...) //Not in blew

    bManager := NewCollectionManager(s)

    bManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_B() //returns []B

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    cManager := NewCollectionManager(s)

    cManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_C() //returns []C

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    w := bManager.Update()

    k := cManager.Update()


    x := bManager.Get("foo").(B)

    y := cManager.Get("bar").(C)

    }


    type IA interface {

    ID() string

    }

    type B struct {

    id string

    z string

    ...

    }

    func (b B) ID() string {

    return b.id

    }

    type C struct {

    id string

    w int

    ...

    }


    func (c C) ID() string {

    return c.id

    }


    type CollectionManager struct {

    s *Sourcer

    all map[string]IA

    gf func(s *Sourcer) []IA

    }


    func NewCollectionManager(s *Sourcer) *CollectionManager {

    cm = &CollectionManager{

    s: s,

    }

    return cm

    }


    func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

    gf = f

    }


    func (c *CollectionManager) Update() {

    res := f(c.s)

    for i := range res {

    id = res[i].ID()

    all[id] = res[i]

    }

    }
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Dec 31, 2014 at 4:17 pm

    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:
    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mike at Jan 1, 2015 at 12:06 am
    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items

    If you do not embedded that logic into a generic/base manager, you need to
    copy that to every different type collection manager that you are managing.
    I am ok not to use a collection manager but I do not know how to avoid the
    duplication with the right design. In other words, I want to think in Go
    way, I just do not know what the Go way is in here?
    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor wrote:

    On Wed, Dec 31, 2014 at 2:34 AM, Mike <mikes...@gmail.com <javascript:>>
    wrote:
    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tamás Gulácsi at Jan 1, 2015 at 8:27 am
    What is a collection manager for?

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Atdiar at Jan 1, 2015 at 9:09 am
    Would be great if you could provide a concrete example, because I admit I'm
    not sure I understand exactly what you are trying to do.

    From what I have understood, you have Updators of different types which
    needs to communicate changes to Updatees.
    I haven't done this for several updators but I guess it would be similar.

    // An Updator registers the list of objects it needs to keep up-to-date.
    type Updator struct{
          updatees []updatable
    }

    // Interface that is common to all updatees
    type updatable interface{
         Update()
    }

    // ChangeMe is a specific updatee (can be in its own pkg)
    type ChangeMe struct{
          ...
    }

    func (c *ChangeMe) Update(){ //updating logic that is relative to the
    ChangeMe type}

    That's the basic idea I would think of, but I am not sure that corresponds
    even remotely to what you have in mind.

    On Thursday, January 1, 2015 12:06:37 AM UTC, Mike wrote:

    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items

    If you do not embedded that logic into a generic/base manager, you need to
    copy that to every different type collection manager that you are managing.
    I am ok not to use a collection manager but I do not know how to avoid the
    duplication with the right design. In other words, I want to think in Go
    way, I just do not know what the Go way is in here?
    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor wrote:
    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:

    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Atdiar at Jan 1, 2015 at 9:12 am
    And ofc, the Updator would call Update() recursively on the list it is
    holding when needed.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Egon at Jan 1, 2015 at 9:35 am

    On Thursday, 1 January 2015 02:06:37 UTC+2, Mike wrote:
    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    Are you implementing a calculator, a networked game, a website, some
    connection manager, email server, certificate authority....?
    i.e. tell the full story of why you need to do these things. Why should the
    end user care about these things?

    + Egon

    If you do not embedded that logic into a generic/base manager, you need to
    copy that to every different type collection manager that you are managing.
    I am ok not to use a collection manager but I do not know how to avoid the
    duplication with the right design. In other words, I want to think in Go
    way, I just do not know what the Go way is in here?
    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor wrote:
    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:

    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mike at Jan 1, 2015 at 10:43 pm
    Unfortunately, I can not talk about what my employer is building. I guess,
    I am trying to understand how some of the missing OO stuff are handled in
    GO. Here is the problem again.

    We have few remote collections of different types, B, C,... like in below.

    type B struct {

         id string

         z string

         ...

    }

    type C struct {

         id string

         w int

         ...

    }


    ...

    A collection of them can be retrieved through some given (not under our
    control) sourcer/driver. Every method on the sourcer return a collection of
    the target type. for instance



    s := NewSourcer(...)


    results1 = s.GetAll_A() //returns []A

    results2 = s.GetAll_B() //returns []B

    ...

    We do not have the option to use sourcer to get each item one by one. All
    or nothing.

    We now want to monitor changes on any of the items in the collection but we
    want to implement that logic generically. My current approach is this way.
    We define an interface like this


    type IA interface {

         ID() string

         Changed(i IA) bool

    }


    and make sure B,C,.. implement that


    func (b B) ID() string {

         return b.id

    }


    func (b B) Changed(i IA) bool {

         ... //How even B see fit as what change it is to it

    }


    func (c C) ID() string {

         return c.id

    }


    func (c C) Changed(i IA) bool {

         ...

    }


    Now we put together the awful generic collection manager


    type CollectionManager struct {

         s *Sourcer

         gf func(s *Sourcer) []IA

         all map[string]IA

         ...

    }


    func NewCollectionManager(s *Sourcer) *CollectionManager {

         cm = &CollectionManager{

             s: s,

         }

         return cm

    }


    func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

         gf = f

    }


    func (c *CollectionManager) Run() {

        for{

             select {

                 case <-time.After(2):

                     res := f(c.s)

                     for i := range res {

                        id = res[i].ID()

                        if res[i].Changed(c.all[id]) {

                              c.all[id] = res[i]

                              //Not somehow notify ppl (not my question here on how to)

                        }

                     }

            }

        }

    }


    And to initialize things, I have to say

    func main() {

         s := NewSourcer(...)

         bManager := NewCollectionManager(s)

         bManager.Register(func(s *Sourcer) []IA {

             results = s.GetAll_B() //returns []B

             newResults := make([]IA, len(results))

                 for i, res := range results {

                     newResults[i] = IA(res)

                 }

             return newResults

         })

         cManager := NewCollectionManager(s)

         cManager.Register(func(s *Sourcer) []IA {

             results = s.GetAll_C() //returns []C

             newResults := make([]IA, len(results))

                 for i, res := range results {

                     newResults[i] = IA(res)

                 }

             return newResults

         })

         go bManager.Run()

         go cManager.Run()

             ....

    }


    which is ugly.


    I hope this makes clear. My apologies if the question is still vague but frankly, I can not explain it any better. I am trying to figure how would I implement such logic in GO that does not result into the above spaghetti but still meet the purpose of having a generic collection manager for all these different types.


    In other words, with inheritance and generics this is easy to do in Java but how do you do so in Go?


    Happy New Year Btw! :)


    On Thursday, January 1, 2015 1:35:15 AM UTC-8, Egon wrote:


    On Thursday, 1 January 2015 02:06:37 UTC+2, Mike wrote:

    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    Are you implementing a calculator, a networked game, a website, some
    connection manager, email server, certificate authority....?
    i.e. tell the full story of why you need to do these things. Why should
    the end user care about these things?

    + Egon

    If you do not embedded that logic into a generic/base manager, you need
    to copy that to every different type collection manager that you are
    managing. I am ok not to use a collection manager but I do not know how to
    avoid the duplication with the right design. In other words, I want to
    think in Go way, I just do not know what the Go way is in here?
    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor wrote:
    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:

    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Egon at Jan 1, 2015 at 11:18 pm

    On Friday, 2 January 2015 00:43:51 UTC+2, Mike wrote:
    Unfortunately, I can not talk about what my employer is building.
    Sure, we can understand, simply state it in the initial question then
    people won't bother asking for it. Also when you can't give the original
    problem then sometimes translating the ideas into some sort of game would
    help. (Of course when you simplify/translate, always mention it)

    I guess, I am trying to understand how some of the missing OO stuff are
    handled in GO. Here is the problem again.

    We have few remote collections of different types, B, C,... like in below.

    type B struct {

    id string

    z string

    ...

    }

    type C struct {

    id string

    w int

    ...

    }


    ...
    Do you know these types beforehand?
    How many potential types are there?

    A collection of them can be retrieved through some given (not under our
    control) sourcer/driver. Every method on the sourcer return a collection of
    the target type. for instance
    s := NewSourcer(...)


    results1 = s.GetAll_A() //returns []A

    results2 = s.GetAll_B() //returns []B
    Do you know the methods of the sourcer beforehand?
    Do they always return them for all types or only for some types?

    ...

    We do not have the option to use sourcer to get each item one by one. All
    or nothing.

    We now want to monitor changes on any of the items in the collection but
    we want to implement that logic generically. My current approach is this
    way. We define an interface like this


    type IA interface {

    ID() string

    Changed(i IA) bool

    }
    Can you always keep all the items in the memory for this approach to work?

    and make sure B,C,.. implement that


    func (b B) ID() string {

    return b.id

    }


    func (b B) Changed(i IA) bool {

    ... //How even B see fit as what change it is to it

    }


    func (c C) ID() string {

    return c.id

    }


    func (c C) Changed(i IA) bool {

    ...

    }


    Now we put together the awful generic collection manager


    type CollectionManager struct {

    s *Sourcer

    gf func(s *Sourcer) []IA

    all map[string]IA

    ...

    }


    func NewCollectionManager(s *Sourcer) *CollectionManager {

    cm = &CollectionManager{

    s: s,

    }

    return cm

    }


    func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

    gf = f

    }


    func (c *CollectionManager) Run() {

    for{

    select {

    case <-time.After(2):

    res := f(c.s)

    for i := range res {

    id = res[i].ID()

    if res[i].Changed(c.all[id]) {

    c.all[id] = res[i]

    //Not somehow notify ppl (not my question here on how to)
    Who will listen to these changes? How many will listen these?
    This probably needs to be worked out in tandem to get the best solution.

    When something changes, do they care that the whole collection changed or
    just some particular piece.

    }

    }

    }

    }

    }


    And to initialize things, I have to say

    func main() {

    s := NewSourcer(...)

    bManager := NewCollectionManager(s)

    bManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_B() //returns []B

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    cManager := NewCollectionManager(s)

    cManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_C() //returns []C

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    go bManager.Run()

    go cManager.Run()

    ....

    }


    which is ugly.


    I hope this makes clear. My apologies if the question is still vague but frankly, I can not explain it any better. I am trying to figure how would I implement such logic in GO that does not result into the above spaghetti but still meet the purpose of having a generic collection manager for all these different types.


    In other words, with inheritance and generics this is easy to do in Java but how do you do so in Go?
    A suggestion how to approach these problems,

    First write the non-generic versions without inheritance - and duplicate as
    much code as you need, don't worry about it. But do make it as clean and
    readable as possible!

    If the result is maintainable, then stop - you don't need to make it
    generic.
    If it's not maintainable then try to find interface boundaries for that
    code.


    From the initial review for interface boundaries I would start with
    http://play.golang.org/p/Gk8jWTHS67 (but only iff there is N number of
    different types that the sources can return).

    + Egon


    Happy New Year Btw! :)
    Happy New Year, as well.
    On Thursday, January 1, 2015 1:35:15 AM UTC-8, Egon wrote:


    On Thursday, 1 January 2015 02:06:37 UTC+2, Mike wrote:

    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    Are you implementing a calculator, a networked game, a website, some
    connection manager, email server, certificate authority....?
    i.e. tell the full story of why you need to do these things. Why should
    the end user care about these things?

    + Egon

    If you do not embedded that logic into a generic/base manager, you need
    to copy that to every different type collection manager that you are
    managing. I am ok not to use a collection manager but I do not know how to
    avoid the duplication with the right design. In other words, I want to
    think in Go way, I just do not know what the Go way is in here?
    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor wrote:
    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:

    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mike at Jan 2, 2015 at 12:48 am

    On Thursday, January 1, 2015 3:18:51 PM UTC-8, Egon wrote:
    On Friday, 2 January 2015 00:43:51 UTC+2, Mike wrote:

    Unfortunately, I can not talk about what my employer is building.
    Sure, we can understand, simply state it in the initial question then
    people won't bother asking for it. Also when you can't give the original
    problem then sometimes translating the ideas into some sort of game would
    help. (Of course when you simplify/translate, always mention it)
    Sure. I should say that this remote collection watch is my attempt for that
    and a simplified version of what we are doing.

    I guess, I am trying to understand how some of the missing OO stuff are
    handled in GO. Here is the problem again.

    We have few remote collections of different types, B, C,... like in below.

    type B struct {

    id string

    z string

    ...

    }

    type C struct {

    id string

    w int

    ...

    }


    ...
    Do you know these types beforehand?
    How many potential types are there?
    Yes, I Know. About 100 different types

    A collection of them can be retrieved through some given (not under our
    control) sourcer/driver. Every method on the sourcer return a collection of
    the target type. for instance
    s := NewSourcer(...)


    results1 = s.GetAll_A() //returns []A

    results2 = s.GetAll_B() //returns []B
    Do you know the methods of the sourcer beforehand?
    Do they always return them for all types or only for some types?
    Yes, I do. A separate method for each type (not in my control) and always
    return them for all types

    ...
    We do not have the option to use sourcer to get each item one by one. All
    or nothing.

    We now want to monitor changes on any of the items in the collection but
    we want to implement that logic generically. My current approach is this
    way. We define an interface like this


    type IA interface {

    ID() string

    Changed(i IA) bool

    }
    Can you always keep all the items in the memory for this approach to work?
    Yes, I am assuming for now that I can.
    and make sure B,C,.. implement that


    func (b B) ID() string {

    return b.id

    }


    func (b B) Changed(i IA) bool {

    ... //How even B see fit as what change it is to it

    }


    func (c C) ID() string {

    return c.id

    }


    func (c C) Changed(i IA) bool {

    ...

    }


    Now we put together the awful generic collection manager


    type CollectionManager struct {

    s *Sourcer

    gf func(s *Sourcer) []IA

    all map[string]IA

    ...

    }


    func NewCollectionManager(s *Sourcer) *CollectionManager {

    cm = &CollectionManager{

    s: s,

    }

    return cm

    }


    func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

    gf = f

    }


    func (c *CollectionManager) Run() {

    for{

    select {

    case <-time.After(2):

    res := f(c.s)

    for i := range res {

    id = res[i].ID()

    if res[i].Changed(c.all[id]) {

    c.all[id] = res[i]

    //Not somehow notify ppl (not my question here on how to)
    Who will listen to these changes? How many will listen these?
    This probably needs to be worked out in tandem to get the best solution.
    Other go routines. I am thinking to have a Subscribe method on the
    collection manager that accepts an id and returns a channel of type IA and
    the go routine itself type assert it into the its target type. Not nice but
    someone has to the conversion.

    When something changes, do they care that the whole collection changed or
    just some particular piece.
    only a particular item change with specific id. The entire collection
    change it meaningless.

    }

    }

    }

    }

    }


    And to initialize things, I have to say

    func main() {

    s := NewSourcer(...)

    bManager := NewCollectionManager(s)

    bManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_B() //returns []B

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    cManager := NewCollectionManager(s)

    cManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_C() //returns []C

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    go bManager.Run()

    go cManager.Run()

    ....

    }


    which is ugly.


    I hope this makes clear. My apologies if the question is still vague but frankly, I can not explain it any better. I am trying to figure how would I implement such logic in GO that does not result into the above spaghetti but still meet the purpose of having a generic collection manager for all these different types.


    In other words, with inheritance and generics this is easy to do in Java but how do you do so in Go?
    A suggestion how to approach these problems,

    First write the non-generic versions without inheritance - and duplicate
    as much code as you need, don't worry about it. But do make it as clean and
    readable as possible!

    If the result is maintainable, then stop - you don't need to make it
    generic.
    If it's not maintainable then try to find interface boundaries for that
    code.
    100 copy of same logic is not very maintainable so I need the
    generalization. Specially that other types maybe added in future too. It is
    these proper interface boundaries that are not coming to me.


    From the initial review for interface boundaries I would start with
    http://play.golang.org/p/Gk8jWTHS67 (but only iff there is N number of
    different types that the sources can return).
    there is N number of different types that fit in memory but we need to
    notify to multiple listeners on each item change and not the entire
    collection change. Also, I am getting the following errors. Can you
    actually use Foos as []Foo without explicit conversion?

    http://play.golang.org/p/cCTyWSd1gX

    prog.go:13: invalid argument b (type Collection) for len
    prog.go:19: invalid operation: b[i] (type Collection does not support indexing)




    + Egon

    Happy New Year Btw! :)
    Happy New Year, as well.
    On Thursday, January 1, 2015 1:35:15 AM UTC-8, Egon wrote:


    On Thursday, 1 January 2015 02:06:37 UTC+2, Mike wrote:

    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    Are you implementing a calculator, a networked game, a website, some
    connection manager, email server, certificate authority....?
    i.e. tell the full story of why you need to do these things. Why should
    the end user care about these things?

    + Egon

    If you do not embedded that logic into a generic/base manager, you need
    to copy that to every different type collection manager that you are
    managing. I am ok not to use a collection manager but I do not know how to
    avoid the duplication with the right design. In other words, I want to
    think in Go way, I just do not know what the Go way is in here?

    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor
    wrote:
    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:

    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Egon at Jan 2, 2015 at 9:42 am

    On Friday, 2 January 2015 02:48:45 UTC+2, Mike wrote:

    On Thursday, January 1, 2015 3:18:51 PM UTC-8, Egon wrote:
    On Friday, 2 January 2015 00:43:51 UTC+2, Mike wrote:

    Unfortunately, I can not talk about what my employer is building.
    Sure, we can understand, simply state it in the initial question then
    people won't bother asking for it. Also when you can't give the original
    problem then sometimes translating the ideas into some sort of game would
    help. (Of course when you simplify/translate, always mention it)
    Sure. I should say that this remote collection watch is my attempt for
    that and a simplified version of what we are doing.

    I guess, I am trying to understand how some of the missing OO stuff are
    handled in GO. Here is the problem again.

    We have few remote collections of different types, B, C,... like in
    below.

    type B struct {

    id string

    z string

    ...

    }

    type C struct {

    id string

    w int

    ...

    }


    ...
    Do you know these types beforehand?
    How many potential types are there?
    Yes, I Know. About 100 different types

    A collection of them can be retrieved through some given (not under our
    control) sourcer/driver. Every method on the sourcer return a collection of
    the target type. for instance
    s := NewSourcer(...)


    results1 = s.GetAll_A() //returns []A

    results2 = s.GetAll_B() //returns []B
    Do you know the methods of the sourcer beforehand?
    Do they always return them for all types or only for some types?
    Yes, I do. A separate method for each type (not in my control) and always
    return them for all types

    ...
    We do not have the option to use sourcer to get each item one by one.
    All or nothing.

    We now want to monitor changes on any of the items in the collection but
    we want to implement that logic generically. My current approach is this
    way. We define an interface like this


    type IA interface {

    ID() string

    Changed(i IA) bool

    }
    Can you always keep all the items in the memory for this approach to work?
    Yes, I am assuming for now that I can.
    and make sure B,C,.. implement that


    func (b B) ID() string {

    return b.id

    }


    func (b B) Changed(i IA) bool {

    ... //How even B see fit as what change it is to it

    }


    func (c C) ID() string {

    return c.id

    }


    func (c C) Changed(i IA) bool {

    ...

    }


    Now we put together the awful generic collection manager


    type CollectionManager struct {

    s *Sourcer

    gf func(s *Sourcer) []IA

    all map[string]IA

    ...

    }


    func NewCollectionManager(s *Sourcer) *CollectionManager {

    cm = &CollectionManager{

    s: s,

    }

    return cm

    }


    func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

    gf = f

    }


    func (c *CollectionManager) Run() {

    for{

    select {

    case <-time.After(2):

    res := f(c.s)

    for i := range res {

    id = res[i].ID()

    if res[i].Changed(c.all[id]) {

    c.all[id] = res[i]

    //Not somehow notify ppl (not my question here on how to)
    Who will listen to these changes? How many will listen these?
    This probably needs to be worked out in tandem to get the best solution.
    Other go routines. I am thinking to have a Subscribe method on the
    collection manager that accepts an id and returns a channel of type IA and
    the go routine itself type assert it into the its target type. Not nice but
    someone has to the conversion.

    When something changes, do they care that the whole collection changed or
    just some particular piece.
    only a particular item change with specific id. The entire collection
    change it meaningless.

    }

    }

    }

    }

    }


    And to initialize things, I have to say

    func main() {

    s := NewSourcer(...)

    bManager := NewCollectionManager(s)

    bManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_B() //returns []B

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    cManager := NewCollectionManager(s)

    cManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_C() //returns []C

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    go bManager.Run()

    go cManager.Run()

    ....

    }


    which is ugly.


    I hope this makes clear. My apologies if the question is still vague but frankly, I can not explain it any better. I am trying to figure how would I implement such logic in GO that does not result into the above spaghetti but still meet the purpose of having a generic collection manager for all these different types.


    In other words, with inheritance and generics this is easy to do in Java but how do you do so in Go?
    A suggestion how to approach these problems,

    First write the non-generic versions without inheritance - and duplicate
    as much code as you need, don't worry about it. But do make it as clean and
    readable as possible!

    If the result is maintainable, then stop - you don't need to make it
    generic.
    If it's not maintainable then try to find interface boundaries for that
    code.
    100 copy of same logic is not very maintainable so I need the
    generalization.
    Sure, the point I was making that even if you see beforehand that it will
    be unmaintainable - write the "repeated" version nevertheless, by making
    that version as clean as possible, it sometimes helps to see how to create
    the interface boundaries.

    Also sometimes you can easily generate the similar code.

    Specially that other types maybe added in future too. It is these proper
    interface boundaries that are not coming to me.


    From the initial review for interface boundaries I would start with
    http://play.golang.org/p/Gk8jWTHS67 (but only iff there is N number of
    different types that the sources can return).
    there is N number of different types that fit in memory but we need to
    notify to multiple listeners on each item change and not the entire
    collection change. Also, I am getting the following errors. Can you
    actually use Foos as []Foo without explicit conversion?
    Yeah, no, sorry, I was half asleep when I wrote that... :)

    http://play.golang.org/p/cCTyWSd1gX

    prog.go:13: invalid argument b (type Collection) for len
    prog.go:19: invalid operation: b[i] (type Collection does not support indexing)

    Anyways, without the full context, the best I can come up with is a
    reflection based approach http://play.golang.org/p/6HGpwujXyx. Pass the
    slices around as interface{} or create a seprate type Collection
    interface{} to be more clearer. *Also, if the "ItemsChanged" becomes a
    performance bottleneck then generate the slice comparison code for each
    slice type and keep the reflect based approach as a fallback; i.e. use go
    generate and text/template. The generating the code for each slice type
    should be trivial.*

    PS: I always try not to use reflect, because it can complicate things and
    by using reflect, you may miss the obvious nicer answers.

    Anyways a few other thoughts - see if you can push the changes monitoring
    to the "Sourcer" otherwise you might be moving things around a lot,
    detecting the changes at the "source" might be faster.

    I'm getting an array of changes because it's usually more efficient to
    batch these changes.

    + Egon

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Atdiar at Jan 2, 2015 at 12:44 am
    The way I see it (but we are all being vague now :), you are trying to have
    your Collection manager monitor different collections for changes.
    I would rather have the changes communicated upward to the collection
    manager by each collection.

    For example, the generated collections could have a channel of a certain
    type or maybe just a function can suffice in some cases if you synchronize
    data access appropriately.

    So instead of []A I would create an intermediary structure : (just a schema)
    type ColA struct{
         collection []A
         Update chan Foo
    }

    Basically what I am trying to say is that, it seems, you could reverse the
    communication flow and that would be more appropriate.

    But as Egon said, if you can simplify the problem further, it would help
    clarify things. You are probably still seeing the problem in a Java way :)

    Happy new year.

    On Thursday, January 1, 2015 10:43:51 PM UTC, Mike wrote:

    Unfortunately, I can not talk about what my employer is building. I guess,
    I am trying to understand how some of the missing OO stuff are handled in
    GO. Here is the problem again.

    We have few remote collections of different types, B, C,... like in below.

    type B struct {

    id string

    z string

    ...

    }

    type C struct {

    id string

    w int

    ...

    }


    ...

    A collection of them can be retrieved through some given (not under our
    control) sourcer/driver. Every method on the sourcer return a collection of
    the target type. for instance



    s := NewSourcer(...)


    results1 = s.GetAll_A() //returns []A

    results2 = s.GetAll_B() //returns []B

    ...

    We do not have the option to use sourcer to get each item one by one. All
    or nothing.

    We now want to monitor changes on any of the items in the collection but
    we want to implement that logic generically. My current approach is this
    way. We define an interface like this


    type IA interface {

    ID() string

    Changed(i IA) bool

    }


    and make sure B,C,.. implement that


    func (b B) ID() string {

    return b.id

    }


    func (b B) Changed(i IA) bool {

    ... //How even B see fit as what change it is to it

    }


    func (c C) ID() string {

    return c.id

    }


    func (c C) Changed(i IA) bool {

    ...

    }


    Now we put together the awful generic collection manager


    type CollectionManager struct {

    s *Sourcer

    gf func(s *Sourcer) []IA

    all map[string]IA

    ...

    }


    func NewCollectionManager(s *Sourcer) *CollectionManager {

    cm = &CollectionManager{

    s: s,

    }

    return cm

    }


    func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

    gf = f

    }


    func (c *CollectionManager) Run() {

    for{

    select {

    case <-time.After(2):

    res := f(c.s)

    for i := range res {

    id = res[i].ID()

    if res[i].Changed(c.all[id]) {

    c.all[id] = res[i]

    //Not somehow notify ppl (not my question here on how to)

    }

    }

    }

    }

    }


    And to initialize things, I have to say

    func main() {

    s := NewSourcer(...)

    bManager := NewCollectionManager(s)

    bManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_B() //returns []B

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    cManager := NewCollectionManager(s)

    cManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_C() //returns []C

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    go bManager.Run()

    go cManager.Run()

    ....

    }


    which is ugly.


    I hope this makes clear. My apologies if the question is still vague but frankly, I can not explain it any better. I am trying to figure how would I implement such logic in GO that does not result into the above spaghetti but still meet the purpose of having a generic collection manager for all these different types.


    In other words, with inheritance and generics this is easy to do in Java but how do you do so in Go?


    Happy New Year Btw! :)


    On Thursday, January 1, 2015 1:35:15 AM UTC-8, Egon wrote:


    On Thursday, 1 January 2015 02:06:37 UTC+2, Mike wrote:

    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    Are you implementing a calculator, a networked game, a website, some
    connection manager, email server, certificate authority....?
    i.e. tell the full story of why you need to do these things. Why should
    the end user care about these things?

    + Egon

    If you do not embedded that logic into a generic/base manager, you need
    to copy that to every different type collection manager that you are
    managing. I am ok not to use a collection manager but I do not know how to
    avoid the duplication with the right design. In other words, I want to
    think in Go way, I just do not know what the Go way is in here?
    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor wrote:
    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:

    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mike at Jan 2, 2015 at 1:08 am
    You are right. I am stuck in my Java but seeking my way out properly! :)

    The point behind the collection manager is that each collection do not have
    to know how to update itself and detect changes. That logic is built into a
    generic collection manager. Just make an instance of the generic collection
    manager for your type and done. I can sure copy this logic on every
    collection for each type but that is what I am trying to avoid. My below
    Run() function is a simple sample of such logic. We have a lot of more
    complex but similar kinda of logic and want to encapsulate it, not copy
    around.

    Also we do not want to constantly convert []B or []C to []IA. Maybe I am
    not following your suggestion but that does not seem to address these goals.

    On Thursday, January 1, 2015 4:44:04 PM UTC-8, atd...@gmail.com wrote:

    The way I see it (but we are all being vague now :), you are trying to
    have your Collection manager monitor different collections for changes.
    I would rather have the changes communicated upward to the collection
    manager by each collection.

    For example, the generated collections could have a channel of a certain
    type or maybe just a function can suffice in some cases if you synchronize
    data access appropriately.

    So instead of []A I would create an intermediary structure : (just a
    schema)
    type ColA struct{
    collection []A
    Update chan Foo
    }

    Basically what I am trying to say is that, it seems, you could reverse the
    communication flow and that would be more appropriate.

    But as Egon said, if you can simplify the problem further, it would help
    clarify things. You are probably still seeing the problem in a Java way :)

    Happy new year.

    On Thursday, January 1, 2015 10:43:51 PM UTC, Mike wrote:

    Unfortunately, I can not talk about what my employer is building. I
    guess, I am trying to understand how some of the missing OO stuff are
    handled in GO. Here is the problem again.

    We have few remote collections of different types, B, C,... like in below.

    type B struct {

    id string

    z string

    ...

    }

    type C struct {

    id string

    w int

    ...

    }


    ...

    A collection of them can be retrieved through some given (not under our
    control) sourcer/driver. Every method on the sourcer return a collection of
    the target type. for instance



    s := NewSourcer(...)


    results1 = s.GetAll_A() //returns []A

    results2 = s.GetAll_B() //returns []B

    ...

    We do not have the option to use sourcer to get each item one by one. All
    or nothing.

    We now want to monitor changes on any of the items in the collection but
    we want to implement that logic generically. My current approach is this
    way. We define an interface like this


    type IA interface {

    ID() string

    Changed(i IA) bool

    }


    and make sure B,C,.. implement that


    func (b B) ID() string {

    return b.id

    }


    func (b B) Changed(i IA) bool {

    ... //How even B see fit as what change it is to it

    }


    func (c C) ID() string {

    return c.id

    }


    func (c C) Changed(i IA) bool {

    ...

    }


    Now we put together the awful generic collection manager


    type CollectionManager struct {

    s *Sourcer

    gf func(s *Sourcer) []IA

    all map[string]IA

    ...

    }


    func NewCollectionManager(s *Sourcer) *CollectionManager {

    cm = &CollectionManager{

    s: s,

    }

    return cm

    }


    func (c *CollectionManager) Register(f func(s *Sourcer) []IA) {

    gf = f

    }


    func (c *CollectionManager) Run() {

    for{

    select {

    case <-time.After(2):

    res := f(c.s)

    for i := range res {

    id = res[i].ID()

    if res[i].Changed(c.all[id]) {

    c.all[id] = res[i]

    //Not somehow notify ppl (not my question here on how to)

    }

    }

    }

    }

    }


    And to initialize things, I have to say

    func main() {

    s := NewSourcer(...)

    bManager := NewCollectionManager(s)

    bManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_B() //returns []B

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    cManager := NewCollectionManager(s)

    cManager.Register(func(s *Sourcer) []IA {

    results = s.GetAll_C() //returns []C

    newResults := make([]IA, len(results))

    for i, res := range results {

    newResults[i] = IA(res)

    }

    return newResults

    })

    go bManager.Run()

    go cManager.Run()

    ....

    }


    which is ugly.


    I hope this makes clear. My apologies if the question is still vague but frankly, I can not explain it any better. I am trying to figure how would I implement such logic in GO that does not result into the above spaghetti but still meet the purpose of having a generic collection manager for all these different types.


    In other words, with inheritance and generics this is easy to do in Java but how do you do so in Go?


    Happy New Year Btw! :)


    On Thursday, January 1, 2015 1:35:15 AM UTC-8, Egon wrote:


    On Thursday, 1 January 2015 02:06:37 UTC+2, Mike wrote:

    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This
    logic can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    Are you implementing a calculator, a networked game, a website, some
    connection manager, email server, certificate authority....?
    i.e. tell the full story of why you need to do these things. Why should
    the end user care about these things?

    + Egon

    If you do not embedded that logic into a generic/base manager, you need
    to copy that to every different type collection manager that you are
    managing. I am ok not to use a collection manager but I do not know how to
    avoid the duplication with the right design. In other words, I want to
    think in Go way, I just do not know what the Go way is in here?

    On Wednesday, December 31, 2014 8:17:18 AM UTC-8, Ian Lance Taylor
    wrote:
    On Wed, Dec 31, 2014 at 2:34 AM, Mike wrote:

    Let's say you want to create some generic collection manager that keeps a
    cache of some remote objects of different types which are supplied through
    some king of a sourcer object that always returns a collection of different
    things depending on the method called on it.
    At this point you have decided to do something that is awkward to do
    in Go. Go does not have good support for generic collection managers.
    Wanting to use one sounds like importing a C++/Java approach into Go.
    There is nothing wrong with the C++/Java approach, it's just not a
    good fit for Go. I recommending thinking about why you want a generic
    collection manager in the first place.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jan 5, 2015 at 9:12 pm

    On Wed, Dec 31, 2014 at 4:06 PM, Mike wrote:
    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote collections
    for change and the watch logic is the same across all your types. This logic
    can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    That sounds straightforward to do in Go, by using a slice of some
    appropriate interface type.

    If you do not embedded that logic into a generic/base manager, you need to
    copy that to every different type collection manager that you are managing.
    I am ok not to use a collection manager but I do not know how to avoid the
    duplication with the right design. In other words, I want to think in Go
    way, I just do not know what the Go way is in here?
    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can work
    with all those different slice types. That is hard to do in Go. You
    can do it using the reflect package but that is definitely a last
    resort.

    My first suggestion would be to instead stick exclusively to slices of
    some appropriate interface type. Have all the type-specific work be
    done in methods. Use type assertions as needed.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mike at Jan 6, 2015 at 4:17 pm
    Thank you Ion and Egon for your help. I ended up capturing smaller generic
    parts as embedded types and copying the rest around.

    I love Go but this was a good learning experience as what is less doable
    with Go. Do you consider this a limitation to the language or a good thing
    that people can't really do so?
    On Monday, January 5, 2015 1:12:19 PM UTC-8, Ian Lance Taylor wrote:

    On Wed, Dec 31, 2014 at 4:06 PM, Mike <mikes...@gmail.com <javascript:>>
    wrote:
    Thank you egon and Ian for the response. The use case for a collection
    manager like this is to encapsulate common logic across your different
    types. For instance. you want to watch your multi-type remote
    collections
    for change and the watch logic is the same across all your types. This logic
    can be

    1> Pull All Objects using the registered function every 2 sec
    2> Detect Changed Objects (through a common method on the IA type and
    something common among all types)
    3> Notify a subscriber list with the new items
    That sounds straightforward to do in Go, by using a slice of some
    appropriate interface type.

    If you do not embedded that logic into a generic/base manager, you need to
    copy that to every different type collection manager that you are managing.
    I am ok not to use a collection manager but I do not know how to avoid the
    duplication with the right design. In other words, I want to think in Go
    way, I just do not know what the Go way is in here?
    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can work
    with all those different slice types. That is hard to do in Go. You
    can do it using the reflect package but that is definitely a last
    resort.

    My first suggestion would be to instead stick exclusively to slices of
    some appropriate interface type. Have all the type-specific work be
    done in methods. Use type assertions as needed.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jan 6, 2015 at 6:43 pm

    On Tue, Jan 6, 2015 at 8:17 AM, Mike wrote:
    I love Go but this was a good learning experience as what is less doable
    with Go. Do you consider this a limitation to the language or a good thing
    that people can't really do so?
    In effect this leads us into the generics discussion, which has been
    and will continue to be discussed at length.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Nicolas Riesco at Jan 6, 2015 at 5:47 pm

    On 05/01/15 21:12, Ian Lance Taylor wrote:
    On Wed, Dec 31, 2014 at 4:06 PM, Mike wrote:
    If you do not embedded that logic into a generic/base manager, you need to
    copy that to every different type collection manager that you are managing.
    I am ok not to use a collection manager but I do not know how to avoid the
    duplication with the right design. In other words, I want to think in Go
    way, I just do not know what the Go way is in here?
    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can work
    with all those different slice types. That is hard to do in Go. You
    can do it using the reflect package but that is definitely a last
    resort.
    Go allows conversions and type-assertions between "compatible" interfaces.

    The OP's problem could be written in Go more easily, if Go allowed the
    same between slices/arrays of "compatible" interfaces (see example below).

    What would be the cons?



    // https://play.golang.org/p/qBxIguEnIS

    package main

    type A interface{}

    type B interface {
          A
    }

    func main() {
          var a A
          var b B = 1

          a = b
          a = b.(A)

          as := []A{}
          bs := []B{1, 2, 3}

          as = bs
          as = bs.([]A)
    }

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jan 6, 2015 at 6:44 pm

    On Tue, Jan 6, 2015 at 9:47 AM, wrote:
    On 05/01/15 21:12, Ian Lance Taylor wrote:

    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can work
    with all those different slice types. That is hard to do in Go. You
    can do it using the reflect package but that is definitely a last
    resort.
    Go allows conversions and type-assertions between "compatible" interfaces.

    The OP's problem could be written in Go more easily, if Go allowed the same
    between slices/arrays of "compatible" interfaces (see example below).

    What would be the cons?
    The representation of different interface types differs: they have
    different method tables. The cons would be a hidden behind the scenes
    loop that converts each value. Better to make that cost explicit by
    forcing the programmer to write their own loop, which can be easily
    done in a function.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Nicolas Riesco at Jan 6, 2015 at 6:53 pm

    On 06/01/15 18:44, Ian Lance Taylor wrote:
    The representation of different interface types differs: they have
    different method tables. The cons would be a hidden behind the scenes
    loop that converts each value.
    wouldn't the method table be the same for each value?

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jan 6, 2015 at 7:04 pm

    On Tue, Jan 6, 2015 at 10:53 AM, wrote:
    On 06/01/15 18:44, Ian Lance Taylor wrote:

    The representation of different interface types differs: they have
    different method tables. The cons would be a hidden behind the scenes loop
    that converts each value.
    wouldn't the method table be the same for each value?
    No, the method table depends on the dynamic type, and given a slice of
    some interface type there is no particular reason to expect that each
    value in the slice has the same dynamic type.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mike at Jan 6, 2015 at 6:57 pm
    Actually how expensive those conversions are?
    On Tuesday, January 6, 2015 10:44:51 AM UTC-8, Ian Lance Taylor wrote:

    On Tue, Jan 6, 2015 at 9:47 AM, <nicolas...@gmail.com <javascript:>>
    wrote:
    On 05/01/15 21:12, Ian Lance Taylor wrote:

    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can work
    with all those different slice types. That is hard to do in Go. You
    can do it using the reflect package but that is definitely a last
    resort.
    Go allows conversions and type-assertions between "compatible"
    interfaces.
    The OP's problem could be written in Go more easily, if Go allowed the same
    between slices/arrays of "compatible" interfaces (see example below).

    What would be the cons?
    The representation of different interface types differs: they have
    different method tables. The cons would be a hidden behind the scenes
    loop that converts each value. Better to make that cost explicit by
    forcing the programmer to write their own loop, which can be easily
    done in a function.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jan 6, 2015 at 7:07 pm

    On Tue, Jan 6, 2015 at 10:57 AM, Mike wrote:
    Actually how expensive those conversions are?
    See the conv and assert functions in
    http://golang.org/src/runtime/iface.go .

    But note that for this purpose the expense of each individual
    conversion is unimportant. The important point is that converting
    from a slice of one type to a slice of another type is an O(N)
    operation. In Go we don't want a simple type conversion to hide an
    O(N) operation, with a few exceptions such as []byte to string that
    are considered clearly expensive.

    Ian
    On Tuesday, January 6, 2015 10:44:51 AM UTC-8, Ian Lance Taylor wrote:
    On Tue, Jan 6, 2015 at 9:47 AM, wrote:
    On 05/01/15 21:12, Ian Lance Taylor wrote:

    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can work
    with all those different slice types. That is hard to do in Go. You
    can do it using the reflect package but that is definitely a last
    resort.
    Go allows conversions and type-assertions between "compatible"
    interfaces.

    The OP's problem could be written in Go more easily, if Go allowed the
    same
    between slices/arrays of "compatible" interfaces (see example below).

    What would be the cons?
    The representation of different interface types differs: they have
    different method tables. The cons would be a hidden behind the scenes
    loop that converts each value. Better to make that cost explicit by
    forcing the programmer to write their own loop, which can be easily
    done in a function.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mike at Jan 6, 2015 at 7:17 pm
    I agree. Hiding such thing is not good. While I can dig through the
    generics conversation, what is its current status on generics? 80/20 or
    20/80?
    On Tuesday, January 6, 2015 11:07:08 AM UTC-8, Ian Lance Taylor wrote:

    On Tue, Jan 6, 2015 at 10:57 AM, Mike <mikes...@gmail.com <javascript:>>
    wrote:
    Actually how expensive those conversions are?
    See the conv and assert functions in
    http://golang.org/src/runtime/iface.go .

    But note that for this purpose the expense of each individual
    conversion is unimportant. The important point is that converting
    from a slice of one type to a slice of another type is an O(N)
    operation. In Go we don't want a simple type conversion to hide an
    O(N) operation, with a few exceptions such as []byte to string that
    are considered clearly expensive.

    Ian
    On Tuesday, January 6, 2015 10:44:51 AM UTC-8, Ian Lance Taylor wrote:
    On Tue, Jan 6, 2015 at 9:47 AM, wrote:
    On 05/01/15 21:12, Ian Lance Taylor wrote:

    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can
    work
    with all those different slice types. That is hard to do in Go.
    You
    can do it using the reflect package but that is definitely a last
    resort.
    Go allows conversions and type-assertions between "compatible"
    interfaces.

    The OP's problem could be written in Go more easily, if Go allowed
    the
    same
    between slices/arrays of "compatible" interfaces (see example below).

    What would be the cons?
    The representation of different interface types differs: they have
    different method tables. The cons would be a hidden behind the scenes
    loop that converts each value. Better to make that cost explicit by
    forcing the programmer to write their own loop, which can be easily
    done in a function.

    Ian
    --
    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...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/d/optout.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Egon at Jan 6, 2015 at 8:04 pm

    On Tuesday, 6 January 2015 21:17:20 UTC+2, Mike wrote:
    I agree. Hiding such thing is not good. While I can dig through the
    generics conversation, what is its current status on generics? 80/20 or
    20/80?
    Basically there's no agreement whether it's a good idea or not for Go. And
    users who have been using Go for longer seem to be biased towards that
    generics is not vital at this point.

    https://docs.google.com/document/d/1vrAy9gMpMoS3uaVphB32uVXX4pi-HnNjkMEgyAHX4N4/

    On Tuesday, January 6, 2015 11:07:08 AM UTC-8, Ian Lance Taylor wrote:
    On Tue, Jan 6, 2015 at 10:57 AM, Mike wrote:
    Actually how expensive those conversions are?
    See the conv and assert functions in
    http://golang.org/src/runtime/iface.go .

    But note that for this purpose the expense of each individual
    conversion is unimportant. The important point is that converting
    from a slice of one type to a slice of another type is an O(N)
    operation. In Go we don't want a simple type conversion to hide an
    O(N) operation, with a few exceptions such as []byte to string that
    are considered clearly expensive.

    Ian
    On Tuesday, January 6, 2015 10:44:51 AM UTC-8, Ian Lance Taylor wrote:
    On Tue, Jan 6, 2015 at 9:47 AM, wrote:
    On 05/01/15 21:12, Ian Lance Taylor wrote:

    Here it sounds like you want to have slices of various specific,
    non-interface, types, and you want to write generic code that can
    work
    with all those different slice types. That is hard to do in Go.
    You
    can do it using the reflect package but that is definitely a last
    resort.
    Go allows conversions and type-assertions between "compatible"
    interfaces.

    The OP's problem could be written in Go more easily, if Go allowed
    the
    same
    between slices/arrays of "compatible" interfaces (see example
    below).
    What would be the cons?
    The representation of different interface types differs: they have
    different method tables. The cons would be a hidden behind the scenes
    loop that converts each value. Better to make that cost explicit by
    forcing the programmer to write their own loop, which can be easily
    done in a function.

    Ian
    --
    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...@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 31, '14 at 10:34a
activeJan 6, '15 at 8:04p
posts25
users6
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase