How to have a global variable accessible across all packages - go

I have a main.go file which has:
// running the router in port 9000
func main() {
router,Global := routers.InitApp()
fmt.println(Global)
router.RunTLS(":9000" , "domain.crt" , "domain.key")
}
In router.InitMap I want to declare a global variable which can be accessed throughout my application anywhere. Is is possible? I tried:
func InitApp() (*gin.Engine,string) {
var Global= "myvalue"
router := gin.New()
return router,Global
}
But I can't access the variable Global even in the same package.

declare a variable at the top level - outside of any functions:
var Global = "myvalue"
func InitApp() (string) {
var Global= "myvalue"
return Global
}
Since the name of the variable starts with an uppercase letter, the variable will be available both in the current package through its name - and in any other package when you import the package defining the variable and qualify it with the package name as in: return packagename.Global.
Here's another illustration (also in the Go playground: https://play.golang.org/p/h2iVjM6Fpk):
package main
import (
"fmt"
)
var greeting = "Hello, world!"
func main() {
fmt.Println(greeting)
}
See also Go Tour: "Variables" https://tour.golang.org/basics/8 and "Exported names" https://tour.golang.org/basics/3.

It is better to use the init function for initialisation of global variables. It also will be processed only once even in multiply includes of this package. https://play.golang.org/p/0PJuXvWRoSr
package main
import (
"fmt"
)
var Global string
func init() {
Global = InitApp()
}
func main() {
fmt.Println(Global)
}
func InitApp() (string) {
return "myvalue"
}

My solution:
define the global variable in other package with Set and Get, similar with class set in python
the good part is that you can set global variables in any package, the bad part is that you can mess up the global variables if you use Set not carefully
https://play.golang.org/p/egApePP7kPq
first define global variable
-- globalvar/globalvar.go --
package globalvar
import "fmt"
var Glbv int
func Set(b int) {
Glbv = b
}
func Get() int {
return Glbv
}
func Pr() {
fmt.Printf("inside globarvar = %v \n", Glbv)
} ```
then you can change the global variable in another package
-- otherpackage/otherpackage.go --
package otherpackage
import (
"fmt"
"play.ground/globalvar"
)
func Bar() {
globalvar.Set(3)
}
func Prtf() {
var cc = globalvar.Get()
fmt.Printf("inside otherpackage globalvar=%v \n", cc)
}
main function
package main
import (
"play.ground/globalvar"
"play.ground/otherpackage"
)
func main() {
globalvar.Pr()
otherpackage.Prtf()
globalvar.Set(2)
globalvar.Pr()
otherpackage.Prtf()
otherpackage.Bar()
globalvar.Pr()
otherpackage.Prtf()
}
here is the result
inside globarvar = 0
inside otherpackage globalvar=0
inside globarvar = 2
inside otherpackage globalvar=2
inside globarvar = 3
inside otherpackage globalvar=3

You can also do it like writing a function to initialise the global variable as:
package main
import (
"fmt"
)
func initialise() string {
CommonVariable = "global_variable"
return CommonVariable
}
var CommonVariable string
func main() {
initialise()
fmt.Println(CommonVariable)
}
If you want to take input from user and then initialise it to global variable, just change the line CommonVariable="myvalue" in initialise() function with "Scanf" statement like this:
func initialise() string {
fmt.Scanln(&CommonVariable)
return CommonVariable
}

Related

Assign value to a variable while passing it to a function in Go

I am pretty new to Go and I just wanted to know how do you pass a value to a function while assigning it to a variable.
Eg,In Java
int a;
foo(a = 20);
You can do this only:
package main
import "fmt"
func foo(a int) {
fmt.Println(a)
}
func main() {
a := 20
foo(a)
}

How to call only specific functions that have an annotation or tag

Is there a way to add a tag or annotate some methods so that whenever an event arises all the methods with this tag or annotation get invoked?
How to achieve this in Go?
As others have said, no there are no annotations or tags on functions in Go.
However, it is more than possible to use a map (or slice) and a register function to keep records of other funcs (or interfaces). You just need to manually call that register func (usually in init() of that package).
For example,
package events
var eventFuncs = make(map[string]func())
func Register(event string, f func()) {
eventFuncs[event] = append(eventFuncs[event],f)
}
func Get(event string) []func() {
return eventFuncs[event]
}
And using the package to register:
package xy
import (
"fmt"
"some.url/events"
)
func Call() {
fmt.Println("Ha!")
}
func init() {
events.Register("x",Call)
}
And then call the funcs elsewhere:
package main
import (
"some.url/events"
)
func main() {
for _,f := range pkg.GetEvent("x") { f() }
}

How to implement Python functools.wraps equivalent?

I know I can wrap functions in Go through returning function, bug how to implement Python functools.wraps equivalent in Go? How to attach attribute to functions in Go? Like the code below in Python.
from functools import wraps
def d(f):
def wrapper(*args):
f(*args)
return wrapper
def d_wraps(f):
#wraps(f)
def wrapper(*args):
f(*args)
return wrapper
#d
def f(a=''):
print a
#d_wraps
def g(a=''):
print a
if __name__ == '__main__':
print 'function name: ', f.__name__
f('abc')
print 'function name: ', g.__name__
g('abc')
d does not change function name, d_wraps changes function name. The result is
function name: wrapper
abc
function name: g
abc
I want to use the wrapped function as key at runtime. So I want to keep the function name unchanged after wrapped. How to implement the job that d_wraps does in Go?
How to attach attribute to functions in Go?
No, You can not attach attribute to functions in Go.
How to implement the job that d_wraps does in Go?
You can implement another function call your functions, and call the function with the new name.
package main
import "fmt"
func main() {
g_warp("abc")
}
func g(a string){
fmt.Println(a);
}
func g_warp(a string){
g(a+"_mysuffix");
}
If you want to change the function content but use the same function name, you can use global function variable:
package main
import (
"fmt"
)
func main() {
g = gV2
g("hello")
}
var g = gV1;
func gV1(a string){
fmt.Println(a)
}
func gV2(a string){
gV1(a+"_suffix")
}
If you have a lot of functions to have the same wrap logic, you can pass in the origin function and return the new function:
package main
import (
"fmt"
)
func main() {
g = wrap(g)
g("hello")
f = wrap(f)
f("hello")
}
var g = gV1;
func gV1(a string){
fmt.Println(a)
}
var f = fV1;
func fV1(a string){
fmt.Println(a+" "+a)
}
func wrap(originFn func(a string)) func(a string){
return func(a string){
originFn(a+"_suffix")
}
}

Initialize a variable over a function by reference in golang

If I have a function which takes a reference as an argument and I want to use that function to initialize a variable I need to do this inside the init() function. That solution works, but it smells not really correct to me.
Is there another way to initialize a variable for a package in go like to use the init() function?
I think that there must be a better way. I thought already about a wrapping function, but that makes the logik not better.
I prepared a short and simple example
package main
import (
"fmt"
)
var a string
//A use of a function is not allowed
//foo(&a)
//Need to call init
func init() {
foo(&a)
}
func main() {
fmt.Println(a)
}
func foo(b *string) {
*b = "abc"
}
https://play.golang.org/p/GdBiDFB1KAe
That's fine, or you can just make a pointer and assign it like this:
var a = make("abc")
func main() {
fmt.Println(*a)
}
func make(s string) *string {
return &s
}
playground

In go, how do I make global variables

package main
import (
"fmt"
"bufio"
"os"
)
func main() {
fmt.Print("LOADED!\n")
fmt.Print("insert y value here: ")
inputY := bufio.NewScanner(os.Stdin)
inputY.Scan()
inputXfunc()
}
func inputXfunc() {
fmt.Print("insert x value here: ")
inputX := bufio.NewScanner(os.Stdin)
inputX.Scan()
slope()
}
func slope() {
fmt.Println(inputX.Text())
}
Whenever I run this program, it says, that inputX and inputY are unidentified. How do I make this program use variables that are accessible to all of the functions? All I want to do is devide inputY by inputX then print out the result
I'm just putting my comment as an answer... I would recommend against this however you could just declare the variable at package scope. It would look like this;
package main
import (
"fmt"
"bufio"
"os"
)
var inputX io.Scanner
func main() {
fmt.Print("LOADED!\n")
fmt.Print("insert y value here: ")
inputY := bufio.NewScanner(os.Stdin)
inputY.Scan()
inputXfunc()
}
func inputXfunc() {
fmt.Print("insert x value here: ")
inputX = bufio.NewScanner(os.Stdin) // get rid of assignment initilize short hand here
inputX.Scan()
slope()
}
func slope() {
fmt.Println(inputX.Text())
}
However a better choice would be to change your method definitions to accept arguments and pass the values into them as needed. This would like like so;
func slope(inputX bufio.Scanner) {
fmt.Println(inputX.Text())
}
slope(myInputWhichIsOfTypeIOScanner)
You can create an init() function and make use of it in the main.go by using package like godotenv to set os's environment variables:
global.go file
package global
import (
"log"
"os"
"strconv"
"github.com/joho/godotenv"
)
var (
SERVER_HOST string
SERVER_PORT int
)
func InitConfig() {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
SERVER_HOST = os.Getenv("SERVER_HOST")
SERVER_PORT, _ = strconv.Atoi(os.Getenv("SERVER_PORT"))
}
main.go file
package main
import(
G "path/to/config"
)
func init() {
G.InitConfig()
}
func main() {
G.Init()
}
You will still have to import "G" package in other packages to use the variables, but I think the best way to tackle global variables in Go (or any other languages) is to make use of environment variables.

Resources