Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set a global variable only once in golang

Tags:

go

I have a main.go file which has:

// running the router in port 9000
func main() {
    router := routers.InitApp()
    router.RunTLS(":9000" , "domain.crt" , "domain.key")
}

In another gofile I have

package utils
var ConfigMap = GetAppConfig
func GetAppConfig() map[string]string{
 ....//
}

ConfigMap being a global variable , everytime I try to access utils.ConfigMap map the GetAppConfig function is called. How can I call this function only once while by app initializes and then access the ConfigMap anyehere I want in the go project.

like image 336
codec Avatar asked Jul 29 '16 11:07

codec


People also ask

How do you avoid global variables in Golang?

Create a function that uses the global variable The caller can not predict what database configuration used for it, except by inspecting the function and digging the definition of the globals. There are many solutions to avoid this, Like pass the Db variable in the function signature like this.

Does go have static variables?

Static Type Declaration in Go A static type variable declaration provides assurance to the compiler that there is one variable available with the given type and name so that the compiler can proceed for further compilation without requiring the complete detail of the variable.


2 Answers

This is what package init() functions are for. They are executed once, before your package can be reached "from the outside":

var ConfigMap map[string]string

func init() {
    // Init ConfigMap here
}

Note that such exported global variables should be protected if you want to allow concurrent use. It would be unfeasible to leave this to the users of the package.

For this purpose, you should declare ConfigMap unexported:

var configMap[string]string

And provide a getter function which would properly protect it with a Mutex:

var confMu = &sync.Mutex{}

func Config(name string) string {
    confMu.Lock()
    defer confMu.Unlock()
    return configMap[name]
}
like image 178
icza Avatar answered Oct 08 '22 11:10

icza


I believe there is a typo in the code that you posted. You define the configMap outside the init function like this:

var configMap map[string]string

This is fine but inside the init you also have this:

var configMap = map[string]string{}

Here you are shadowing the configMap that you have outside the init function meaning that you have declared the variable again inside the init. As a result when you access the variable outside of the init function you will get the global variable which is still empty. If you remove the var inside the init it would work fine.

configMap = map[string]string{}

Here's a quick demonstration.

There is another typo in the original question:

var configMap = GetAppConfig

This should be:

var configMap = GetAppConfig()

You are assigning the function to a variable rather than result of the function.

like image 39
Arash Avatar answered Oct 08 '22 09:10

Arash