Declarations and scope
A declaration binds a non-blank identifier to a constant, type, type parameter, variable, function, label, or package. Every identifier in a program must be declared. No identifier may be declared twice in the same block, and no identifier may be declared in both the file and package block.
That’s a lot of words to basically say: You need to name your things. And your things need unique names.
No real surprises here. Well, except one.
Notice it says “no identifier may be declared in both the file and package block.” This is the one exception to the normal scoping rules. And honestly, it’s not that surprising, because it’s pretty intuitive to use.
In practical terms, it means your file-scoped identifiers can conflict with package-scoped identifiers in other files of the same package.
Confused?
Here’s an example. Imagine these files are in the same directory (and thus the same package):
one.go
package main
import "fmt"
func main() {
fmt.Println("testing")
}
two.go
package main
var fmt string
If we try to compile this program, we’ll get the following error:
./two.go:3:5: fmt already declared through import of package fmt ("fmt")
./one.go:3:8: other declaration of fmt
Quotes from The Go Programming Language Specification Version of December 15, 2022