Can multiple go routines hinder variables in a same function? - go

My question might be dumb but please bear with me. If two go-routines are calling the same function, will they share variables in that function? Is it safe to declare variables inside the function and use freely?
func main() {
go func1(1)
go func1(2)
}
func func1(a int) {
something := a
// do something
}
In the above code when two go-routines are calling same function will they hinder with the variable declaration of each other? Will the value of something change if the go routines are not in order or something?

will they hinder the variable declaration - no. essentially it's a function.. so if you're declaring the variable inside the function.. there won't be any issues and it works normally.
but if the variable is not declared inside the function but outside the scope of the function then the order of the go routines will hinder the value
for example
import (
"fmt"
"time"
)
var something int
func test(a int) {
something += a
fmt.Println("something", something)
}
func main() {
fmt.Println("Testing Something")
go test(20)
go test(3)
time.Sleep(1 * time.Second) // crude way without using channels or waitgroup.
}

Related

Same pointer different values, in multi file main package

My project is a login-register web server that consists of multiple files and uses another package in which the Manager struct is defined.
Overview of my files:
my-package/
main.go
handlers.go
...
I have a variable: var M *Manager declared in main.go before definition of main() and it is assigned inside main():
var M *Manager
func main() {
...
M = InitManager(...)
...
}
handleLogin(...) and handleRegister(...) are functions defined in handlers.go that use the M variable:
func handleRegister(...){
...
fmt.Println("M:", M)
M.Log1("logging informations...")
...
}
func handleLogin(...) {
...
fmt.Println("M:", M)
M.GetAccount(login)
...
}
When I go to /loginor /register and the appropriate handle function is triggered it displays: M: <nil>
To find out something more I modified main() as shown below:
var M *Manager
func main() {
...
go func() { // for debugging
for {
fmt.Println("main() goloop1: M:", M)
time.Sleep(time.Second / 2)
}
}()
M = InitManager(...)
go func() { // for debugging
for {
fmt.Println("main() goloop2: M:", M)
time.Sleep(time.Second / 2)
}
}()
...
}
and the output:
main() goloop2: M: &{...data as expected...}
main() goloop1: M: <nil>
main() goloop2: M: &{...data as expected...}
main() goloop1: M: <nil>
...
My question are:
How do pointers work then if one pointer gives out two values?
How to fix my issue and properly plan code (if that was the cause) to avoid this in future?
Per the Go Memory Model, the provided code writes and reads M without proper synchronization, which is a data race and leads to undefined behavior (see icza's comment).
The compiler "assumes" that the code is properly synchronized (this is the responsibility of the developer) and so it is "allowed" to assume that M is never modified inside the infinite loops, so it may use a copy in a given register or stack memory location over and over, leading to the surprising output.
You may use a sync.Mutex to protect every access to the global *Manager variable M, as in this modified code.
Also beware of variable shadowing! It is possible to write M := f() instead of M = f(), resulting in an unrelated local variable, not affecting the global variable.
My solution:
I have added init.go:
my-package/
main.go
handlers.go
...
init.go
I moved global variables like M and CONFIG_MAP into the init.go file:
package main
import ...
var CONFIG_MAP = LoadConfig()
var M *asrv.Manager = InitManager()
func LoadConfig() map[string]string {
// return map from 'conf.json' file
}
func InitManager() *asrv.Manager {
// return Manager configured with CONFIG_MAP
// other functions also use CONFIG_MAP that is the reason why it is global
}
func init() {
LoadTemplatesFiles() // load templates and assign value
// to a variable declared in templates.go
}
This way handler functions (handleLoginGet etc.) in handlers.go could properly read M.
This fix just made my program work and I still don't know what is the proper way of handling this type of situation, that is why I added more info under EDIT in my question.

Calling a variable from another function in go

I know that variables are pass by value in go. However, I want to call a variable that in inside a func outside this function. Let me give you an example:
package main
import (
"fmt"
)
func Smile(){
A := 5
}
func main() {
fmt.Println(A)
}
This gives me undefine A.
what is the best way to pass A ? Should I use a pointer? How do I do that?
It's not possible to print the value of the A variable declared in the Smile() function from main().
And the main reason for that is that the variable A only exists if code execution enters the Smile() function, more precisely reaches the A variable declaration. In your example this never happens.
And even if in some other example this happens (e.g. Smile() is called), an application may have multiple goroutines, and multiple of them may be executing Smile() at the same time, resulting in the app having multiple A variables, independent from each other. In this situation, which would A in main() refer to?
Go is lexically scoped using blocks. This means the variable A declared inside Smile() is only accessible from Smile(), the main() function cannot refer to it. If you need such "sharing", you must define A outside of Smile(). If both Smile() and main() needs to access it, you have to make it either a global variable, or you have to pass it to the functions that need it.
Making it a global variable, this is how it could look like:
var a int
func smile() {
a = 5
fmt.Println("a in smile():", a)
}
func main() {
smile()
fmt.Println("a in main():", a)
}
This outputs (try it on the Go Playground):
a in smile(): 5
a in main(): 5
Declaring it local in main() and passing it to smile(), this is how it could look like:
func smile(a int) {
fmt.Println("a in smile():", a)
}
func main() {
a := 5
fmt.Println("a in main():", a)
smile(a)
}
Output (try it on the Go Playground):
a in main(): 5
a in smile(): 5
The best way is, https://godoc.org/golang.org/x/tools/go/pointer
Pointers
Ex:
func getCar() {
car := Vehicles.Car{}
setModel(&car)
// model ("BMW") will be available here
}
func setModel(car *Vehicles.Car) {
car.Model = "BMW"
}

Turning []interface{} into arguments to a non-variadic function

I am looking for an elegant way to unzip a list of arguments in Go. I do not want to use a variadic function for that purpose because in my usecase when writing a function I already know the number of arguments and I want to keep that part simple. However in my usecase the parameters arrive as []interface{}.
I could not find a solution but hey maybe someone out there already knows how to do that?
package main
import (
"fmt"
)
// NON-VARIADIC greater
func greet(n1, n2 string) {
fmt.Printf("%s %s\n", n1, n2)
}
func main() {
l := []interface{}{"hello", "world"}
// works
greet(l[0].(string), l[1].(string))
// does not work: "./args.go:20: not enough arguments in call to greet"
//greet(l...)
// is there something more elegant to unzip the list?
}
You could create a "generic" caller using reflect package, although this comes with overhead and lacks type safety. Unless you have some special case situation and don't know what you want to call in the code, it would be wiser to use the snippet from your question which works, but you consider not elegant.
Example usage of reflect which could be your starting point:
package main
import (
"fmt"
"reflect"
)
func call(f interface{}, args []interface{}) {
// Convert arguments to reflect.Value
vs := make([]reflect.Value, len(args))
for n := range args {
vs[n] = reflect.ValueOf(args[n])
}
// Call it. Note it panics if f is not callable or arguments don't match
reflect.ValueOf(f).Call(vs)
}
func greet(n1, n2 string) {
fmt.Printf("%s %s\n", n1, n2)
}
func main() {
l := []interface{}{"hello", "world"}
call(greet, l)
}
// Output: hello world
https://play.golang.org/p/vbi3CChCdV
I'm not quite sure what you're trying to do. If you want a way to easily pass a slice of two empty interfaces to a function that accepts two strings, you can create a little helper:
func twoStrings(vs []interface{}) (string, string) {
return vs[0].(string), vs[1].(string)
}
Use it as
greet(twoStrings(l))
Playground: http://play.golang.org/p/R8KFwMUT_V.
But honestly, it seems like you're doing something wrong, trying to make the Go type system to do something it cannot do.

why the "infinite" for loop is not processed?

I need to wait until x.Addr is being updated but it seems the for loop is not run. I suspect this is due the go scheduler and I'm wondering why it works this way or if there is any way I can fix it(without channels).
package main
import "fmt"
import "time"
type T struct {
Addr *string
}
func main() {
x := &T{}
go update(x)
for x.Addr == nil {
if x.Addr != nil {
break
}
}
fmt.Println("Hello, playground")
}
func update(x *T) {
time.Sleep(2 * time.Second)
y := ""
x.Addr = &y
}
There are two (three) problems with your code.
First, you are right that there is no point in the loop at which you give control to the scheduler and such it can't execute the update goroutine. To fix this you can set GOMAXPROCS to something bigger than one and then multiple goroutines can run in parallel.
(However, as it is this won't help as you pass x by value to the update function which means that the main goroutine will never see the update on x. To fix this problem you have to pass x by pointer. Now obsolete as OP fixed the code.)
Finally, note that you have a data race on Addr as you are not using atomic loads and stores.

Is there idiomatic scoped semantics in golang?

I wonder if there is any idiomatic way to represent scoped semantics. By scoped I mean things like:
scoped mutex (oneliner instead of explicit Lock + deffered Unlock),
logging function (or any code block) entrance and exit,
measuring execution time.
Example code for first two bullets:
package main
import "log"
import "sync"
func Scoped(m *sync.Mutex) func() {
m.Lock()
return func() {
m.Unlock()
}
}
func Log(what string) func() {
log.Println(what, "started")
return func() {
log.Println(what, "done")
}
}
func main() {
defer Log("testing")()
m := &sync.Mutex{} // obviously mutex should be from other source in real life
defer Scoped(m)()
// use m
}
https://play.golang.org/p/33j-GrBWSq
Basically we need to make one function call just now (eg mutex lock), and one call should be postponed to defer (eg mutex unlock). I propose just returning unnamed function here, but it can be easily named (return struct with function field).
There is only one problem: user can forget to 'call' result of first call.
This code is (can be) idiomatic?
Take anonymous function as a scope:
func() {
Entrance()
defer Exit()
// anything you want to do in this scope
}()
Your proposed solution is already nice. You return a value of func type which you also have to call at the end of the defer.
You can avoid that (returning a func value), but there have to be 2 function calls, one that logs the start event and another one that logs the end event.
The alternative is to make a function call which produces the parameter value of the function that is deferred (rather than returning a function) which is evaluated with the defer statement, and this way it still can remain one line.
You can also try it on the Go Playground:
func start(s string) string {
fmt.Println("Started", s)
return s
}
func end(name string) {
fmt.Println("Ended", name)
}
func main() {
defer end(start("main"))
fmt.Println("Doing main's work...")
}
Output:
Started main
Doing main's work...
Ended main
I do not believe there is an idiomatic way to do this. I'm not sure why you'd want to either, is it really so bad to write
m.Lock()
defer m.Unlock()
?
I think question isn't relevant to Go idiomaticity, Seems it's generally better to reason about code when function behave identically either call. To keep state I'd better make an object and define function as method on that object. Means something like
type message string
func (foo message) Log(bar string){
if bar==nil{doSomethingSpecial()}
switch foo{
case something: doSomething()
...
case nil: doSomethingInitial()
default: doDefault()
}
log.Println(bar, "started")
foo=bar
}

Resources