If I have a package-scoped variable like this:
var (
bus *Bus // THIS VARIABLE
)
// Bus represents a repository bus. This contains all of the repositories.
type Bus struct {
UserRepository *UserRepository
// ...
}
...and I give access to the bus
variable on my repositories so that they can access each other, do I need to use any sort of mutex if they can be used concurrently?
Quick pseudocode of what would happen:
// Router
router.GET("/user/:id", c.FindUser)
// Controller
func (c *UserController) FindUser(w http.ResponesWriter, r *http.Request) {
w.Write([]byte(c.UserService.FindUser(r.Get("id"))))
}
// Service
func (s UserService) FindUser(id int) *domain.User {
return s.UserRepository.FindByID(id)
}
// Repository
func (r UserRepository) FindByID(id int) *domain.User {
// This is where the package-scope `bus` variable will be used
}
In the FindByID
function, I may use the package-scoped bus
variable, which of course can be accessed concurrently since it will be called whenever an HTTP request triggers it, and those are all handled concurrently.
If all you do is reading the content of variable - then no, you do not need mutex. However, if you ever mutate its state, then you need to protect it.
Two concurrent writes or concurrent write and read can cause problems. If your writes are rare, you might want to use RWMutex. It will allow multiple readers to access, but not together with a writer.
Also, check out race detector. It is best effort detector, so it does not guarantee that you do not have race condition, but it can detect some use cases. Also note that you need to cause race in order for race detector to detect it, so writing tests that use your bus
concurrently or simulating real conditions has to be done.