package main import ( "fmt" "sync" ) type Resource struct { data int } func (r *Resource) increment() { r.data++ } type Client struct { id int resource Resource mu sync.RWMutex } type ActiveClients struct { clients []*Client mu sync.RWMutex } func (ac *ActiveClients) add(client *Client) { ac.mu.Lock() defer ac.mu.Unlock() if ac.clients == nil { ac.clients = make([]*Client, 0) } ac.clients = append(ac.clients, client) } func (ac *ActiveClients) incrementResource(clientId int) { ac.mu.RLock() defer ac.mu.RUnlock() for _, existingClient := range ac.clients { if existingClient.id == clientId { existingClient.mu.Lock() defer existingClient.mu.Unlock() existingClient.resource.increment() return } } } type anError struct { errorMsg string } func (m anError) Error() string { return m.errorMsg } func (ac *ActiveClients) getResource(clientId int) (Resource, error) { ac.mu.RLock() defer ac.mu.RUnlock() for _, existingClient := range ac.clients { if existingClient.id == clientId { existingClient.mu.RLock() defer existingClient.mu.RUnlock() return existingClient.resource, nil } } return Resource{}, anError{"could not find resource"} } var wg sync.WaitGroup func main() { var users ActiveClients users.add(&Client{id: 3}) wg.Add(10) for i := 0; i < 10; i++ { go func() { users.incrementResource(3) wg.Done() }() } wg.Wait() res, err := users.getResource(3) if err != nil { fmt.Println(err) } else { fmt.Printf("resource data = %v\n", res.data) } }