FAQ
Hello all,

Sorry for a naive beginner question, I'm probably missing something obvious.

I'm trying to do something like the following: for a struct/interface
Parent, I want to have several children, global maps where the children
reside:

m1 map[int]Child1
m2 map[int]Child2
m3 map[int]Child3

and then a general function like

func UpdateElement( id int, m map[int]Parent ) {
p := m[id]
p.ParentMethod()
m[id] = p
}

that would accept m1, m2, and m3 for some

func (Parent *p) ParentMethod() {
[do something that changes p]
}

Go FAQ says that I cannot directly convert []T to []interface{}; copying
entire maps is not an option. What would be the best way to do this? I
don't absolutely must have a single update function but I want to avoid
code duplication as much as possible. I don't care whether Parent is a
struct or an interface as long as it works, although struct would be better
since the children do have common fields, and ParentMethod is supposed to
touch the fields.

Thank you!
With best regards,
Sergey Nikolenko.

--

Search Discussions

  • Chl at Oct 5, 2012 at 2:47 pm
    I don't think you need the updateElement function. Instead, i think you
    should just do, m[id].parentmethod().

    And on the question on inheritance i believe you want to look at embedding
    anonymous fields in a struct. Here's an example:
    http://play.golang.org/p/DqJqFp2pbt
    On Friday, October 5, 2012 7:40:29 PM UTC+8, Sergey Nikolenko wrote:

    Hello all,

    Sorry for a naive beginner question, I'm probably missing something
    obvious.

    I'm trying to do something like the following: for a struct/interface
    Parent, I want to have several children, global maps where the children
    reside:

    m1 map[int]Child1
    m2 map[int]Child2
    m3 map[int]Child3

    and then a general function like

    func UpdateElement( id int, m map[int]Parent ) {
    p := m[id]
    p.ParentMethod()
    m[id] = p
    }

    that would accept m1, m2, and m3 for some

    func (Parent *p) ParentMethod() {
    [do something that changes p]
    }

    Go FAQ says that I cannot directly convert []T to []interface{}; copying
    entire maps is not an option. What would be the best way to do this? I
    don't absolutely must have a single update function but I want to avoid
    code duplication as much as possible. I don't care whether Parent is a
    struct or an interface as long as it works, although struct would be better
    since the children do have common fields, and ParentMethod is supposed to
    touch the fields.

    Thank you!
    With best regards,
    Sergey Nikolenko.
    --
  • Sergey Nikolenko at Oct 5, 2012 at 4:39 pm
    Thank you! Unfortunately, this does not seem to solve the problem. First, I
    cannot take the address of a map item:
    http://play.golang.org/p/aOUITFwZtc

    Second, even with the proper syntax that runs with one map I cannot use
    such map as an argument:
    http://play.golang.org/p/COtgWlQYW_
    In this example, ChildUpdate works as intended, but ParentUpdate doesn't ("cannot
    use m1 (type map[int]child1) as type map[int]parent in function argument").
    The question was if it is possible to get ParentUpdate to work somehow so
    that I could pass both m1 and m2 to it.

    Sorry that I didn't think of the playground in the first place, would be
    much easier to ask the question with it.

    Sergey
    On Friday, October 5, 2012 6:47:25 PM UTC+4, chl wrote:

    I don't think you need the updateElement function. Instead, i think you
    should just do, m[id].parentmethod().

    And on the question on inheritance i believe you want to look at embedding
    anonymous fields in a struct. Here's an example:
    http://play.golang.org/p/DqJqFp2pbt
    On Friday, October 5, 2012 7:40:29 PM UTC+8, Sergey Nikolenko wrote:

    Hello all,

    Sorry for a naive beginner question, I'm probably missing something
    obvious.

    I'm trying to do something like the following: for a struct/interface
    Parent, I want to have several children, global maps where the children
    reside:

    m1 map[int]Child1
    m2 map[int]Child2
    m3 map[int]Child3

    and then a general function like

    func UpdateElement( id int, m map[int]Parent ) {
    p := m[id]
    p.ParentMethod()
    m[id] = p
    }

    that would accept m1, m2, and m3 for some

    func (Parent *p) ParentMethod() {
    [do something that changes p]
    }

    Go FAQ says that I cannot directly convert []T to []interface{}; copying
    entire maps is not an option. What would be the best way to do this? I
    don't absolutely must have a single update function but I want to avoid
    code duplication as much as possible. I don't care whether Parent is a
    struct or an interface as long as it works, although struct would be better
    since the children do have common fields, and ParentMethod is supposed to
    touch the fields.

    Thank you!
    With best regards,
    Sergey Nikolenko.
    --
  • Luther at Oct 5, 2012 at 8:08 pm

    On Friday, October 5, 2012 12:39:38 PM UTC-4, Sergey Nikolenko wrote:
    Thank you! Unfortunately, this does not seem to solve the problem. First,
    I cannot take the address of a map item:
    http://play.golang.org/p/aOUITFwZtc
    Since the method takes a pointer receiver, the map needs to hold pointers:
    http://play.golang.org/p/awgtim9q9S
    Look especially at line 18.

    That *should* remove the need for an Update function. Does that solve your
    problem?

    --
  • Sergey Nikolenko at Oct 8, 2012 at 9:22 am
    Thank you! It does work, but it still didn't let me pass the maps of
    different children as arguments -- or am I missing something?

    I have already rewritten it differently, though, just returning a new copy
    of the struct, which has led to something like

    http.HandleFunc("/object/", func(w http.ResponseWriter, r *http.Request) {
    log.Println("Object handler starting for " + r.URL.Path[len("/object/"):])
    template.Execute(w, m[getId(r, "object", defaultId)].Update())
    })

    which is probably good enough until Update() grows too hairy.

    Still, just for my education -- I've tried your approach, and I was amazed
    that the memory consumption didn't grow at all. Isn't a map
    like map[int]*child supposed to store an extra pointer per item? It would
    probably be noticeable for me -- I have maps with lots of small structs. Or
    does Go somehow optimize it behind the curtains?

    Thanks!
    Sergey

    On Saturday, October 6, 2012 12:08:03 AM UTC+4, Luther wrote:
    On Friday, October 5, 2012 12:39:38 PM UTC-4, Sergey Nikolenko wrote:

    Thank you! Unfortunately, this does not seem to solve the problem. First,
    I cannot take the address of a map item:
    http://play.golang.org/p/aOUITFwZtc
    Since the method takes a pointer receiver, the map needs to hold pointers:
    http://play.golang.org/p/awgtim9q9S
    Look especially at line 18.

    That *should* remove the need for an Update function. Does that solve your
    problem?
    --
  • Chl at Oct 8, 2012 at 11:22 am
    Here's a version that allows you to update the map regardless if its
    child1, child2, or child3:
    http://play.golang.org/p/5UNO4ZDQfh

    I think it should be true that a pointer is stored for each item in
    map[int]*child. However, each pointer is only 4 Bytes. I think you don't
    need to worry about overhead unless you have more than 100million + items
    (~ 400MB) .

    On Monday, October 8, 2012 5:22:28 PM UTC+8, Sergey Nikolenko wrote:

    Thank you! It does work, but it still didn't let me pass the maps of
    different children as arguments -- or am I missing something?

    I have already rewritten it differently, though, just returning a new copy
    of the struct, which has led to something like

    http.HandleFunc("/object/", func(w http.ResponseWriter, r *http.Request) {
    log.Println("Object handler starting for " + r.URL.Path[len("/object/"):])
    template.Execute(w, m[getId(r, "object", defaultId)].Update())
    })

    which is probably good enough until Update() grows too hairy.

    Still, just for my education -- I've tried your approach, and I was amazed
    that the memory consumption didn't grow at all. Isn't a map
    like map[int]*child supposed to store an extra pointer per item? It would
    probably be noticeable for me -- I have maps with lots of small structs. Or
    does Go somehow optimize it behind the curtains?

    Thanks!
    Sergey

    On Saturday, October 6, 2012 12:08:03 AM UTC+4, Luther wrote:
    On Friday, October 5, 2012 12:39:38 PM UTC-4, Sergey Nikolenko wrote:

    Thank you! Unfortunately, this does not seem to solve the problem.
    First, I cannot take the address of a map item:
    http://play.golang.org/p/aOUITFwZtc
    Since the method takes a pointer receiver, the map needs to hold pointers:
    http://play.golang.org/p/awgtim9q9S
    Look especially at line 18.

    That *should* remove the need for an Update function. Does that solve
    your problem?
    --
  • Jedy Wu at Oct 5, 2012 at 5:02 pm
    hi. I don't know if it's the best way, but you may use reflect.

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

    --
  • Sergey Nikolenko at Oct 5, 2012 at 5:12 pm
    Thanks a lot! It does work!
    Is it good go style? Looks a bit hacky...
    On Friday, October 5, 2012 7:27:32 PM UTC+4, Jedy Wu wrote:

    hi. I don't know if it's the best way, but you may use reflect.

    http://play.golang.org/p/ovyil_Ru8D
    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedOct 5, '12 at 1:09p
activeOct 8, '12 at 11:22a
posts8
users4
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase