When to use global variables - go

I've heard many times that you should avoid global variables.
In my example I declared a global myTypes variable only to avoid declaring that variable over and over again in a function call or something similar.
Is this how it should be done? Is there a better way? A more testable way?
var myTypes = map[string]string{
"type1": "tpl1",
"type2": "tpl2",
}
func AFunc(someType string) string {
fmt.Sprintf("this is your type %s", myTypes[someType])
}
func main() {
AFunc("type1")
}

Not all global variables are bad. In your case:
The global variable is in the main package and therefore only accessible by a single program. This is ok.
The global variable is initialized once and not modified thereafter. This is ok.
On the other hand, whenever a global variable is modified during the program’s execution, the program becomes more difficult to understand. Therefore it should be avoided.
In a package that is meant to be reusable, global variables should be avoided since then two users of that package might influence each other. Imagine if the json package had a global variable var Indent bool. Such a variable is better to be hidden inside a data structure like JsonFormatter that gets created anew each time someone wants to format some JSON.

One usual way is to use Method Value
Consider a struct type T with two methods, Mv, whose receiver is of type T, and Mp, whose receiver is of type *T.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
The expression
T.Mv
yields a function equivalent to Mv but with an explicit receiver as its first argument; it has signature
func(tv T, a int) int
You can see an example of Method Value in this thread
// TODO: Get rid of the global variable.
var foo service
func handleFoo(w http.ResponseWriter, req *http.Request) {
// code that uses foo
}
func main() {
foo = initFoo()
http.HandleFunc("/foo", handleFoo)
}
One way to get rid of that global variable is to use method values:
type fooHandler struct {
foo service
}
func (h fooHandler) handle(w http.ResponseWriter, req *http.Request) {
// code that uses h.foo
}
func main() {
foo := initFoo()
http.HandleFunc("/foo", fooHandler{foo}.handle)
}
A new official approach for your global values is introduced in Go 1.7 with context.Context#Values.
Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.
See "How to correctly use context.Context in Go 1.7"
Finally, in addition of being hard to test, global values can prevent vendoring.
See "To vendor or not to vendor, that is a question"
Many Go’s libaries have exported package variables. Those variables can be viewed as certain global states of a certain package.
Prior vendoring era, we can go get each imported package once and the global state of each imported package can be shared within all other imported packages.
Some devs may take it as granted and simply manipulate those global states at will.
However, with vendoring each imported package may have its own view of global states. Now a dev may found it impossible to change other package’s view of global state

You're not modifying myTypes, just reading it, so it's not a variable at all, it's a constant, and would be defined as such if Go supported it (and make sure you don't mutate it -- unfortunately Go doesn't allow you to enforce "constness" like other languages do). Global constants are mostly fine.
If you were to modify myTypes, e.g. by providing a function to add new types at runtime, then yes, it's a bad idea to retain myTypes as global state. You might just get away with it as long as you do it only in your "main program" which you're sure will never be a package to be imported by other code, but you don't know where this code might end up / get copied to (or even just used from multiple places in the same package), so why risk it. If this becomes a package that gets imported by other packages, things may work fine as long as there's not more than one such "client" package is active at runtime, but as soon as somebody links together several such packages into one binary, all those user packages will stomp over each other's data in the global myTypes. If a client package expects to only see the myTypes that it put in earlier, this will break if there's another client with different expectations. So packages that work fine when used individually may break when used together, with no way to fix this except changing the shared code. So just don't do it. It's a shame that Google themselves use global state in some of their own public stuff, e.g. in the standard "flag" package and things like "glog" which uses it and thus inherits the problem. Don't do it.

Related

Thread safe mutable configuration in Go

I'm surprised to see the lack of (in any) modules for a configuration module in Go which is thread safe for concurrent reads/writes.
I'm surprised there is no easy method to basically have something like https://github.com/spf13/viper, but thread safe.. where the Get/Set holds a Lock.
what's the right Go way to handle this without bloating code?
I normally use: https://github.com/spf13/viper however if the program for example as a GUI configuration is changeable during runtime, this package doesn't work.
I started doing the following
var config struct {
lock sync.RWMutex
myString string
myInt int
}
func main() {
config.lock.RLock()
_ = config.myString // any read
config.lock.RUnlock()
}
however this becomes very very tedious when accessing members to each time Lock/Unlock every single access for a read or a write and code becomes bloated and repetitive.
I typically use a configuration struct that is retrieved and updated atomically. This allows multiple fields to be updated in a single "transaction" and is easy to implement/use.
With Go1.18 and earlier this can be implemented with atomic.Value and wrap with some simple helper functions to convert the type from interface{} to your *config.
It is even simpler with atomic.Pointer in Go 1.19:
package main
import (
"sync/atomic"
)
type config struct {
str string
num int
}
var cfg atomic.Pointer[config]
func main() {
// Store initial configuration.
cfg.Store(&config{str: "foo", num: 42})
// Clone and modify multiple fields.
newCfg := *cfg.Load()
newCfg.str = "bar"
newCfg.num++
cfg.Store(&newCfg)
// Retrieve a value.
_ = cfg.Load().str
}
With Go1.18 and earlier you can use atomic.Value and wrap them with some simple helper functions to convert the type from interface{} to your *config.

Is there an efficient way to initialize a fixed array in Go without polluting the package namespace?

Here's an implementation of a type which stores a syslog Facility value:
package main
import (
"fmt"
)
// Facility - as defined in RFC 5424
type Facility uint8
var facilityName []string = []string{
"kernel",
"user",
"...",
"local7",
}
func (s Facility) String() string {
if int(s) < len(facilityName) {
return facilityName[s]
} else {
return fmt.Sprintf("facility(%d)!", int(s))
}
}
func UnknownFacility() Facility {
return Facility(1) // "user"
}
The problem with this is that it puts it puts facilityName in the package namespace. The alternative is to create this array or slice inside the String() function, but this creates a new slice/array on every call to String(). The generated code isn't efficient.
Is there a way of doing this efficiently and not polluting the namespace?
UnknownFacility() also feels like Hungarian Notation...
The short answer seems to be No.
The Go compiler (1.18.2) doesn't optimize creating a "constant" array / slice in a function, and there's no equivalent in Go of a C/C++ static variable. Such arrays therefore need to be stored in a package variable to avoid the overhead of recreating them on every function call. (See https://godbolt.org/z/TGPE75Kdf for example compiler output).
There's no mechanism to limit the visibility of a variable to a limited number of functions inside a package. (Go lacks an equivalent to a C++ anonymous namespace)
I'm working around this with a naming convention of prefixing variable names which only need file scope with _filename so they can't collide and are easy to distinguish in IDE auto-completion.
Whether adding variable names which only need file or function scope to the internal package namespace is a significant concern is a different question.

Map to store generic type functions in Go

I am trying to create a Map with String and functions as key and Value. It works if all functions are of same signature but my requirement is to store functions of different signature in the same map. Is this possible in Go?
package main
import "fmt"
func main() {
functions := buildFunctions()
f := functions["isInValid"]
// f("hello")
}
func buildFunctions() map[string]func() bool {
functions := map[string]func() bool{
"isInValid": isInValid,
"isAvailable": isAvailable,
}
return functions
}
func isInValid(s string) bool {
fmt.Println("Invalid ", s)
return true
}
func isAvailable(s string, s1 string) bool {
return true
}
https://play.golang.org/p/ocwCgEpa_0G
Go is a strongly typed language. So, it's not possible the way, it is possible with, say python. But just like python, once you do this, you loose the benefit of compile time error checks, and your runtime error checking has to be full-proof.
Here's what you can do:
Use map[string]interface{} type for your function map, which enables you to store anything. But then you are responsible to correctly type assertion at the time of calling. Problem is that, in most cases, if while calling a function, you could know the type of function, may be you might not need a map in the first place.
Use a map[string]string or map[string]interface{} as the argument, and return type in all the functions that are supposed to go into this map. Or at least put all the variable arguments into this map.
eg.
map[string](func (name string, age int, other_attributes
map[string]interface{}) (map[string]interface{}, error))
But again, each function call should provide the correct arguments, and there should also be checks inside the functions, to see (with non-panic version of map lookup), if the parameters are correctly provided, if not, you can return a custom error like ErrInvalidParametersPassed. (playing the role of an interpreter). But you will still have lesser chances of messing up, compared to first option. As the burden of type assertion will be on the function implementation, and not the caller. Caller just needs to fetch it's required values, which it anyways needs to know about.
But yet, best option would be to redesign your actual solution in a way, so that it can be done without going this road. As #bereal suggested in comments, it's good to have separate maps if possible, or maybe use a superset of arguments if they aren't too different, or too many. If there are just a few arguments, even switch case could be clean enough. Look for ways that cheat/bypass compile time checks, when you are truly convinced that there is no other elegant way.

go how to check if a function exists

Is there any way to check if a func exists in Go?
In PHP I might do something like
if(function_exists('someFunction')) {
//...
}
but I have not been able to figure out how to do this in Go
Any help on this will be greatly received.
A little more context on what you're trying to do would help.
As you note in your own comment, if you try to call a function Go checks at compile-time if the function exists, most of the times.
One exception that comes to my mind is when you use interface{} and you want to check that a method exists before calling it. For this you can use type checks.
Example:
package main
import "fmt"
// a simple Greeter struct
// with a Hello() method defined
type Greeter struct {
Name string
}
func (m *Greeter) Hello() string {
return "hello " + m.Name
}
var x interface{}
func main() {
x = Greeter {Name:"Paolo"} // x is a interface{}
g,ok := x.(Greeter) // we have to check that x is a Greeter...
if ok {
fmt.Println(g.Hello()) // ...before being able to call Hello()
}
}
Another scenario I can think of is that you're creating your own tool for Go that requires parsing go files before compiling them. If so, Go provides help in the for of the parser package
There's no way to do that (and for good!). The reason is that Go is a compiled language and does not support loadable modules (yet, at least) so functions can't come and go at runtime, and hence whether or not a top-level function exists, you know by defintion: if a given source file imports a package containing the function of interest1, that function is visible in this source file. Or this function is declared in the same package this source file belongs to and hence it's also available. In all the other cases the function is not available. Note that a function might be compiled in the program but still not visible in a given source file while compiling, so the whole definition of visibility as you put it does not exist in Go.
On the other hand you might want some generality. Generality in Go is achieved via interfaces. You might define an interface and then require a type to implement it. Checking that a type implements an interface is done via a neat trick.
An update from 2021-12-29.
The support for loadable modules was added in Go 1.8 in the form of the plugin package and has since then matured to support most mainline platforms except Windows.
Still, this solution is not without problems—for instance, see #20481.
1Without renaming that module to nothing, but let's not touch this for now.
Provided your thing is an interface value, type assert, something like this:
if Aer, ok := thing.(interface{MethodA()}); ok {
Aer.MethodA()
}
If thing is a struct, assign it to an interface variable first,
because type assertions only work on interface values.
It wouldn't hurt to define a named interface instead of using the
nonce one, but for simple cases like this it's not worth it.
Recently I had a need for figuring out if a struct has a particular function or not.
Here is another way using reflection :
package main
import (
"fmt"
"reflect"
)
type FuncRegistry struct {}
func (fr FuncRegistry) Hi() {
fmt.Println("function Hi")
}
func (fr FuncRegistry) Hello() {
fmt.Println("function Hello")
}
func functionExists(obj interface{},funcName string) bool {
mthd := reflect.ValueOf(obj).MethodByName(funcName)
if mthd.IsValid() {
fmt.Printf("Function '%s' exists \n",funcName)
return true
}
fmt.Printf("Function '%s' does not exist\n",funcName)
return false
}
// Main function
func main() {
var fr FuncRegistry
functionExists(fr,"Hi")
functionExists(fr,"Hello")
functionExists(fr,"Fail")
}
This sounds a lot like a XY problem. Please tell what you are trying to do. As far as I know, this is something you can't really do the same way as in PHP.
However, you could create a map with function names as keys. Add the functions there manually or generate the contents by parsing the source files before the compilation or at run time. Parsing the source seems like a dirty hack though.

How do I properly structure a package with sub packages in Go where a single type will be the receiver on most of the methods?

I'm currently in the design stage of writing a utility library that will make interaction with the x-go-binding a bit easier. (I've done this before with Python and xpyb.) For example, it will help with querying information defined in the EWMH spec and binding keys to callback functions. (And much more.) So as my initial idea for a package layout, consider:
xutil
ewmh
keybind
Where each is its own package. (Similar to how the standard library's image package is setup.)
What's unique about my situation is that almost every x-go-binding call requires some combination of an xgb connection object or a root window identifier. Therefore, it makes sense to me to store this information in a struct like so:
type XUtilConnection struct {
conn xgb.Conn
root xgb.Id
// a few other things, like a mapping of events to callbacks
}
So that I'd have a factory that could be used like so:
xconn = xutil.NewXUtilConnection(blah blah)
And it could be used like:
xconn.get_active_window()
xconn.bind_key("Shift-a", my_callback_fun)
There may also be functions like:
keybind.get_keycode("a")
ewmh.get_atom("_NET_ACTIVE_WINDOW")
My problem of course is that receivers, to my knowledge, can only be of types that have been declared in the same package. If I separate my packages, I cannot use my XUtilConnection type as a receiver in any of my sub-packages.
I suspect that my answer is going to be making this one big package separated into different logical files, but I fear that this might lead to namespace clutter. (For example, implementing the EWMH spec is probably on the order of 100+ functions.)
I am also aware that I could define a new container type in each sub-package for my XUtilConnection object. (I've heard that this should be a struct containing a single member XUtilConnection to avoid casting.) But this seems like a really messy situation to me, and would prevent the kind of semantics I'd like. (i.e., using an XUtilConnection struct to call methods in several different modules.)
I would suggest to use embedding.
In package xutil:
type XUtilConnection struct {
*ewmh.EWMH // Embed all methods of *ewmh.EWMH
*keybind.KeyBind // Embed all methods of *keybind.KeyBind
}
In package xutil/ewmh:
type EWMH struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some EWMH methods:
func (e *EWMH) GetAtom(name string) { ... }
func (e *EWMH) ...
In package xutil/keybind:
type KeyBind struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some keybind methods:
func (k *KeyBind) GetKeyCode(s string) { ... }
func (k *KeyBind) ...
This will enable you to directly call EWMH's and KeyBind's methods on values of type *XUtilConnection:
var c *XUtilConnection = ...
c.GetAtom("_NET_ACTIVE_WINDOW") // Call (*emwh.EWMH).GetAtom(string)
c.GetKeyCode("a") // Call (*keybind.KeyBind).GetKeyCode(string)
I'm not sure if I understood correctly the problem (I'm confused by seeing package names where they seem to be discussed as method receivers?), but I guess passing around an interface instead of the [*]struct would enable satisfying it from within any package. One can also always do something like (totally untested code):
package foo
type Foo interface { Bar(); Baz() }
----
package qux
import "foo"
type qux struct { foo.Foo; myStuff t }
func Foo(f foo.Foo) foo.Foo {
return qux{f, &t{}}
}
func (q qux) Bar() {
// smthg
}
To e.g. "override" f.Bar in package qux and "inherit" f.Baz() unaltered.

Resources