Reputation: 99687
Given that I have an slice of structs of type User
Users := make([]User)
I am listening for TCP connections, and when a user connects, I'm adding an new user to this slice.
The way I've done this, is by setting up a NewUsers channel
NewUsers := make(chan User)
Upon new TCP connects, a User gets sent to this channel, and a central function waits for a User to arrive to add it to the Users slice.
But now I would like multiple subsystems (packages/functions) to use this list of Users. One function might simply want to receive a list of users, while a different function might want to broadcast messages to every user, or just users matching a certain condition.
How do multiple functions (which are possibly executed from different goroutines) safely access the list of users. I see two possible ways:
Option 1 seems very convoluted and would generate a fair bit of duplication, but my understanding that Mutexes are best to be avoided if you try to stick to the "Share Memory By Communicating" mantra.
Upvotes: 1
Views: 2077
Reputation: 10258
The idiomatic Go way to share data between concurrent activities is summed up in this:
Do not communicate by sharing memory; instead, share memory by communicating.
Andrew Gerrand blogged about this, for example.
It need not be overly-complex; you can think of designing internal microservices, expressed using goroutines with channels.
In your case, this probably means designing a service element to contain the master copy of the list of users.
The main advantages of the Go/CSP strategy are that
But...
There are times when a safely shared data structure (protected by mutexes) will be sufficient now and always. It might then be argued that the extra complexity of goroutines and channels is a non-requirement.
A safely shared list data structure is something you will find several people have provided as open-source APIs. (I have one myself - see the built-ins in runtemplate).
Upvotes: 3
Reputation: 99341
The mutex approach is the best, safest and most manageable approach to that problem and is the fastest.
Channels are complex beasts on the inside and are much slower than a rwmutex-guarded map/slice.
Upvotes: 2