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.
Using global variables causes very tight coupling of code. Using global variables causes namespace pollution. This may lead to unnecessarily reassigning a global value. Testing in programs using global variables can be a huge pain as it is difficult to decouple them when testing.
Golang Global Variable Typically, global variables are defined on top of the program before the main function. After declaration, a global variable can be accessed and changed at any part of the program.
Always prefer local over global. If you need to pass the data in as multiple parameters, so be it. At least then you're explicitly saying what data your function depends on. Having too many parameters is certainly a problem, but offloading some of them as globals isn't the answer.
Global variables should be used when multiple functions need to access the data or write to an object. For example, if you had to pass data or a reference to multiple functions such as a single log file, a connection pool, or a hardware reference that needs to be accessed across the application.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With