Declarations and scope
…
The scope of a declared identifier is the extent of source text in which the identifier denotes the specified constant, type, variable, function, label, or package.
This definition isn’t necessarily specific to Go. Most modern languages have a concept of scope that’s pretty similar. What mainly differs between languages is the rules for where sopes begin and end, or some essoteric features like hoisting in JavaScript. (You don’t need to understand hoisting–it’s not a Go concept. I only mention it as a point of contrast.)
Go is lexically scoped using blocks:
We just learned about blocks. And starting tomorow we’ll dig into the specific rules.
But for now, the most important thing here is that Go uses lexical scope, as opposed to dynamic scope. Since Go doesn’t use dynamic scope, we won’t get into the weeds on what it is, but it’s useful to understand the basics so you know what Go doesn’t do, to avoid surprises.
Perhaps most famously, languages like bash and PowerShell typically use dynamic scope, although there certainly are others. Let’s look at an example in bash, as most of us should have at least some familiarity with bash or a similar scripting language.
str="begin"
echo "start: str=$str"
function inner {
echo "inner: str=$str"
}
function outer {
local str="outer"
inner
}
outer
echo "end: str=$str"
When executed, this script outputs:
start: str=begin
inner: str=outer
end: str=begin
Quotes from The Go Programming Language Specification Version of December 15, 2022