The golang package "net/http" uses the global variable DefaultServeMux to register handlers. Is this considered a good practice or even an golang idiom? Is it a global variable after all?
The two main reasons not to use global variables are AFAIK 1) that they add to complexity and 2) are problematic in concurrent programs.
Maybe 1) is not considered important in this case because the developer can choose not to use DefaultServerMux? What about 2)? Are global variables always thread/goroutine safe in Go? Still, I'm surprised that it's used in Go's standard library. I've never seen such practice in other languages / standard libraries.
Is it a global variable after all?
Yes. The variable is defined on root level, which makes it global throughout the package.
However, this is not a global variable which stores all the sensible information of the net/http
package. It is merely a convenience setup which uses the content of the net/http
package to provide an quickstart opportunity to the user. This also means, that is does not add much complexity.
Is this considered a good practice or even an golang idiom?
IMO, it is good practice to aid the user with the usage of a package. If you're finding that you could save the user some time by providing a good default configuration, do so.
However, you should be careful when you're about to export variables. They should be made ready for concurrent access. The DefaultServeMux
(or better, the underlying ServeMux
), for example, is using a mutex to be thread safe.
Are global variables always thread/goroutine safe in Go?
No. Without proper synchronization (mutex, channel, ...), everything that is accessed concurrently is problematic and will most certainly blow everything to bits and pieces.
I've never seen such practice in other languages / standard libraries.
Python's logging
module, for example, provides a function to retrieve the root logging object, which one can call methods on to customize the logging behaviour. This could be seen as a global object, as it is mutable and defined in the module.
The globvar is, in this case, as safe and as good choice as the analogue seen in e.g package "log" is.
IOW, claim 1 is as vague as it can get and claim 2 is constrained: sometime/somewhere true, otherwise false == doesn't hold in general even though used just like that.