FAQ
I have a struct type that consists of maps of other structs, which I want
to manipulate through methods. Here is a simplification:

type Reconciler struct {
registers map[string]CashRegister
}
func(r *Reconciler) AddEntry(register string, amount int) {
reg, ok := r.registers[register]
if !ok {
// make a new CashRegister for register, assign it to "reg"
}
reg.Add(amount)
}
type CashRegister struct {
// some fields
}
func(c *CashRegister) Add(amount int) {
// mutate some state in the CashRegister
}

Now the program creates a Reconciler, goes through a list of entries and
adds them, then puts the Reconciler onto a channel for something else to
work with. The problem (you probably see it already) is that the
Reconciler's state never changes. The line "reg.Add(amount)" changes a copy
of the value stored in the map, not the value stored in the map. But I
can't say "r.registers[register].Add(amount)" because the compiler
complains that isn't a pointer type. Clearly I need to operate on the
actual values, not copies of them.

My next thought is that I need to change the definition of Reconciler so I
manipulate pointers, not values:

type Reconciler struct {
registers map[string]*CashRegister
}

Is that the solution? Is that going to cause any problems with sending the
value on the channel? I thought I saw somewhere that you should only send
values on channels, not pointers, or there could be problems with
concurrency and safety.

--

Search Discussions

  • Volker Dobler at Nov 21, 2012 at 12:48 pm
    Untried (but sounds reasonable)
    After reg.Add(amount) reg will have the right value, but
    it is a copy of the CashRegister stored in Reconciler.
    Thus just write this correct value back. Add
    r.register[register = reg
    after reg.Add(amount)

    Am Mittwoch, 21. November 2012 13:06:53 UTC+1 schrieb Boris:
    I have a struct type that consists of maps of other structs, which I want
    to manipulate through methods. Here is a simplification:

    type Reconciler struct {
    registers map[string]CashRegister
    }
    func(r *Reconciler) AddEntry(register string, amount int) {
    reg, ok := r.registers[register]
    if !ok {
    // make a new CashRegister for register, assign it to "reg"
    }
    reg.Add(amount)
    }
    type CashRegister struct {
    // some fields
    }
    func(c *CashRegister) Add(amount int) {
    // mutate some state in the CashRegister
    }

    Now the program creates a Reconciler, goes through a list of entries and
    adds them, then puts the Reconciler onto a channel for something else to
    work with. The problem (you probably see it already) is that the
    Reconciler's state never changes. The line "reg.Add(amount)" changes a copy
    of the value stored in the map, not the value stored in the map. But I
    can't say "r.registers[register].Add(amount)" because the compiler
    complains that isn't a pointer type. Clearly I need to operate on the
    actual values, not copies of them.

    My next thought is that I need to change the definition of Reconciler so I
    manipulate pointers, not values:

    type Reconciler struct {
    registers map[string]*CashRegister
    }

    Is that the solution? Is that going to cause any problems with sending the
    value on the channel? I thought I saw somewhere that you should only send
    values on channels, not pointers, or there could be problems with
    concurrency and safety.
    Yes, that would allow r.registers[register].Add(amount).
    Nothing is wrong with sending pointers over a channel.
    Just make sure there is a clear ownership of all the objects
    and this ownership is properly transferred. As I understand your
    solution you are sending Reconciler over the channel, and this
    contains already a map which is a reference type (so basically
    a pointer).

    V.

    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedNov 21, '12 at 12:06p
activeNov 21, '12 at 12:48p
posts2
users2
websitegolang.org

2 users in discussion

Volker Dobler: 1 post Boris: 1 post

People

Translate

site design / logo © 2021 Grokbase