How to lock concurrent access to all struct fields internally? Let's say I have a struct:
type Data struct {
ID string
Size int
//... and more fields
}
That will be used in another struct:
type Project struct {
mu sync.Mutex
MetaData Data
//... and more fields
}
How could I modify/get MetaData struct and use mutex for that while not exposing its mutex to the outer packages? I know I could use Get/Set methods, but what if I needed to modify one field of Data struct (it wouldn't be very good/clean if every field had a get/set method with the same shared mutex)? Could you recommend a way/pattern to have a struct-wise mutex that would be locked/unlocked internally?
How about something like this?
type Data struct {
ID string
Size int
//... and more fields
}
type Project struct {
mu sync.Mutex
metaData Data
//... and more fields
}
func (p *Project) AccessMetaData(f func(*Data)) {
p.mu.Lock()
defer p.mu.Unlock()
f(&p.metaData)
}
I was curious about this so I tested this, and if the parent struct is locked, the child struct is also locked. Try it locally as go playground seems to be deterministic.
package main
import (
"fmt"
"sync"
)
type testGroup struct {
sync.Mutex
items map[string]*test
}
type test struct {
x int
}
var str string = "test"
func increment(t *testGroup, wg *sync.WaitGroup) {
t.Lock()
t.items[str].x = t.items[str].x + 1
t.Unlock()
wg.Done()
}
func main() {
var w sync.WaitGroup
tg := testGroup{}
tg.items = make(map[string]*test)
tg.items[str] = &test{}
for i := 0; i < 1000; i++ {
w.Add(1)
go increment(&tg, &w)
}
w.Wait()
fmt.Println("final value of x", tg.items[str].x)
}
Try commenting out t.Lock()
and t.Unlock()
in increment()
function