In GOLANG, Is there a way to make a variable's scope local to a file within a package?
In my case, there are 2 files ex1.go and ex02.go. ex01.go defines a global variable
var wg sync.WaitGroup
which is used across functions in that file.
In another file ex02.go (which has no relation with ex01.go except that both ex01.go and ex02.go belong to the same class of problems - i.e. concurrency), I can't define a variable for waitGroup as
var wg sync.WaitGroup
I get an error - "variable name is re-declared in this block"
Is there a way to keep the variable names from spilling over to the other files?
For the purpose of variable scoping, files have no meaning in Go. Think of all files in a package as if they would be concatenated, which (simplified) is exactly what happens before compilation.
That means: No, there is no way of scoping a variable to a file.
If you need two global WaitGroup
s, you need to define them as individual variables.
Only explicitly imported identifiers have file's scope. Say in file wg.go you define
package wg
var Wg sync.WaitGroup
// and all staff common to class of problems - i.e. concurrency
and then you can in file ex1.go
import wg
wg.Wg.Add(1) //use locally to file
same in ex2.go
I recommend taking the information below and appropriately applying it to your specific problem. Most of the examples below are from This Medium article.
There are several characteristics of Go's variable declarations and scoping that are consistent with other languages and some that are more particular to Go.
The more consistent characteristics deal with blocks and variable declarations. If you declare a variable, v
, in a block than every block nested to this can 'see' v
. If you redeclare a inside one of these nested blocks then as you leave this inner block you lose that value to a and regain the old value.
examples:
func main() {
{
v := 1
{
fmt.Println(v)
}
fmt.Println(v)
}
// “undefined: v” compilation error
// fmt.Println(v)
}
> ./bin/sandbox
1
1
In thise ^ example you can see that a variable's value is 'seen' down scopes nested from its declaration
v := 1
{
v = 2 // assignment
fmt.Println(v)
}
fmt.Println(v)
>./bin/sandbox
2
2
This example expands on that by saying that since the variable v
was declared on the outer scope then I can also reassign, not redeclare, the value of v
and have it take effect on any scope that can 'see' v
.
v := 1
{
v := 2 // short variable declaration
fmt.Println(v)
}
fmt.Println(v)
>./bin/sandbox
2
1
This last example is closer to your original question. This one shows that I can have the same variable name but have multiple declarations with multiple variables depending on my scope. This leads us to the more different
The more different characteristics deal with Go's concept of package private and public declarations and top level identification.
First let's talk about top level identification. Top level identification is declaring a variable, type, or function outside of any other type or function declaration. func main()
is a good example of a top level identification. Now let's think of multiple files in a Go package. One way to think of multiple files in a Go package is to think of them all appended together to make a really long file. With this in mind we can now see why there's no concept of file private variables. There is only package private or package public.
Package private are top level variables that are only visible to the package itself and are not visible to anyone that might import this package. Package public are visible to the entire package and anyone that might import this package. This is depicted solely by the capitalization of the first letter of the name.
// Package Public
func Main(){...}
var MyVar;
type MyType uint64;
// Package Private
func main(){...}
var myVar;
type myType uint64;
Notice that the case does matter and main()
and Main()
do not invoke the same function. You could also use this to solve your problem but I would not recommend just changing the capitalization just to get around the redeclaration.