Assigning Globals in Go
This has bitten me in the butt a few times this week, so I figured I’d blog about it.
Be careful with your scope when you’re assigning values to global variables in Go!⌗
Here’s a quick little example. We have a globally scoped variable, foo
. In our main()
, we call makeSomething()
, which returns to us, we hope, a something
and a nil
error. Then we make that global foo
variable point to that variable.
package main
var foo int
func anInt()(int, error){
return 7, nil
}
func main(){
foo, err := anInt()
if err != nil {
print ("Oh god!")
}
println("foo was assigned the value of", foo)
printFoo()
}
func printFoo(){
println("I see foo as", foo)
}
Easy peasy, right? Nope.
$ go run stuff.go
foo was assigned the value of 7
I see foo as 0
What we’ve done is created a locally scoped variable foo
that disappears once we exit main()
! That’s because :=
is a short-form variable declaration and assignment. The compiler believes we are declaring a variable foo
and assigning it the value returned by anInt()
.
Let’s run through a few possible variations:
foo alreay exists⌗
func main(){
foo := 3
foo, err := anInt() // Weirdly, no error here
if err != nil { // Local foo is delcared,
print ("Oh god!") // assigned 3, then assigned 7.
}
println("foo was assigned the value of ", foo)
printFoo()
}
Just assign⌗
func main(){
foo, err = anInt() // Compiler error!
if err != nil { // undefined: err
print ("Oh god!")
}
println("foo was assigned the value of", foo)
printFoo()
}
Use a temporary variable⌗
Of course, if we do this:
func main(){
f, err := anInt()
if err != nil {
print ("Oh god!")
}
foo = f
println("foo was assigned the value of", foo)
printFoo()
}
we see:
$ go run stuff.go
foo was assigned the value of 7
I see foo as 7
…which is what we’d expect. However, that’s a little fugly. Let’s tidy that up a bit.
Pre-declare your error⌗
func main(){
var err error
foo, err = anInt()
if err != nil {
print ("Oh god!")
}
println("foo was assigned the value of ", foo)
printFoo()
}
Declare an error
called err
, do the assignment, and then go on with your day.
Anyway, lesson learned. When you’re dealing with globally scoped variables and multiple return values and something doesn’t behave the way you think it should, make sure you’re using the variable you think you’re using.