Thanks, Skip. That fixes it. Is the need for a pointer receiver documented somewhere? It's not something that even crossed my mind given that the neither the compiler nor golint complained. I suppose it makes sense if I think of func (x) foo(y) {} as being an alternate way of writing func foo(x, y) {}. In that case, it's clear that a copy of x is being passed since that's Go's default.
While this topic is still alive, I'd like to ask a follow-on question: Is the use of sync/atomic actually needed in this example or is it sufficient to wrap all accesses in mutex Lock/Unlock (using the same mutex, of course). On Sunday, April 14, 2019 at 12:08:55 PM UTC-4, Skip wrote: > > The receiver for load and update should be the original object not a copy. > > https://play.golang.org/p/XCZC0OVhGMa > > On Sun, Apr 14, 2019, 7:56 AM <michae...@gmail.com <javascript:>> wrote: > >> >> https://play.golang.org/p/6aQYNjojyBD >> >> I'm clearly missing something about the way sync.Mutex and atomic.Value >> work in Go. >> >> I'm attempting to write a pair of concurrency safe methods, load() and >> update(), for accessing a struct. The struct is stored as an atomic.Value >> and accessed with atomic.Load and atomic.Value. I'm also wrapping the >> accesses within a mutex Lock/Unlock. That's probably unneeded for my >> load() method but I added it trying to figure out why it's not returning >> updated info. In my minimal example below (also in the Go Playground link >> above) the output of main() should be: >> >> s={65535} >> v={65535} >> >> but I get >> >> s={65535} >> v={0} >> >> indicating that the updated value is not available after the call to >> update(). >> >> The only thing I'm doing that's a little different from the examples in >> the doc for sync/atomic is passing a function that takes a pointer to a >> struct instance to my update function. I do that to make it easy to write >> code that updates just a few items in the state struct (which in my real >> application has many members instead of just one as shown here.) >> >> Apologies for wasting the group's time if I've overlooked a brain-dead >> error, but I've been fooling with this for several hours now and can't see >> why it shouldn't be working, >> >> >> package main >> >> import ( >> "fmt" >> "sync" >> "sync/atomic" >> ) >> >> type state struct { >> R4000 uint16 >> } >> type guardedState struct { >> v atomic.Value >> } >> >> var stateMutex = sync.Mutex{} >> var gState guardedState >> >> func init() { >> gState.v.Store(state{}) >> } >> >> func (g guardedState) load() state { >> stateMutex.Lock() >> defer stateMutex.Unlock() >> s := gState.v.Load() >> return s.(state) >> } >> >> func (g guardedState) update(f func(*state)) { >> stateMutex.Lock() >> defer stateMutex.Unlock() >> s := g.v.Load().(state) >> f(&s) >> g.v.Store(s) >> } >> >> func main() { >> f := func(s *state) { >> s.R4000 = 65535 >> fmt.Printf("s=%v\n", *s) >> } >> gState.update(f) >> v := gState.load() >> fmt.Printf("v=%v\n", v) >> } >> >> -- >> 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 golan...@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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.