Declarations and scope

June 15, 2023

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


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Scope of imported package names

Continuing our examination of scope… Declarations and scope … The scope of the package name of an imported package is the file block of the file containing the import declaration. The only thing that goes in the file block are imported package names. This is why you must repeat an import statement for every file that uses a symbol from the imported package. So for example, given two files in the same package:


The universe and package blocks

Let’s now dive into the specific scoping rules in Go. There are 8 rules here, and we’ll take one or two per day… Declarations and scope … Go is lexically scoped using blocks: The scope of a predeclared identifier is the universe block. The “universe block”, which encompasses all Go source text, only contains the predeclared identifiers defined in the specification. Specifically, these identifiers are the names of predeclared types, the constants true, false, and iota, the zero value nil, and the built-in functions.


Goto statements

We’ve finished the discussion of the new range-over-func feature, so let’s continue where we left off before the Go 1.23 release, with a feature you’ll rarely, if ever, use. Goto statements A “goto” statement transfers control to the statement with the corresponding label within the same function. GotoStmt = "goto" Label . goto Error Unless your only programming experience has been in the BASIC language, you’ve probably learned to eschew “goto”.

Get daily content like this in your inbox!

Subscribe