This is the 12th day of my participation in the genwen Challenge

The difference between scope and life cycle

  • The scope of the declaration statement corresponds to a text area of the source code; It is a compile-time property.
  • The lifetime of a variable is the period of time during which a variable exists in a program that can be referenced by other parts of the program. Is a runtime concept.

Syntactic blocks and lexical blocks

  • A syntax block is a set of statements enclosed by braces, just like the contents enclosed by a function or loop body bracket. Names declared inside syntactic blocks are not accessible to external blocks.

  • Declarations that are not explicitly wrapped in curly braces in code are called lexical blocks. For the global source code, there is a whole lexical block, called the global lexical block; For each package; Each for, if, and switch statement also corresponds to a lexical block; Each branch of switch or SELECT also has its own syntax block; It also includes explicitly written lexical blocks (bracketed statements).

scope

The scope of a declaration statement is determined by its lexical domain.

  • Built-in types, functions, and constants such as int, len, and true are globally scoped and can therefore be used directly throughout the program.

  • Any name declared outside the function (that is, package-level locale) can be accessed in any source file of the same package.

  • For imported packages, such as the FMT package imported by TempConV, the scope corresponds to the source file level. Therefore, the imported FMT package can only be accessed in the current file. Other source files of the current package cannot access the package imported in the current source file

  • The control-flow label, which follows a break, continue, or GOTO statement, is a function-level scope.

  1. When the compiler encounters a name reference, if it looks like a declaration, it first looks up from the innermost lexical domain to the global scope.

  2. If the lookup fails, an error like “undeclared name” is reported.

  3. If the name is declared separately on the inner and outer blocks, the inner block declaration is found first. In this case, the internal declaration blocks the external declaration with the same name, making the external declaration name inaccessible:

The sample a

The following code has three different variables x because they are defined in different lexical fields

func main(a) {
x := "hello!"
for i := 0; i < len(x); i++ {
x := x[i]
ifx ! ='! ' {
x := x + 'A' - 'a'
fmt.Printf("%c", x) // "HELLO" (one letter per iteration)}}}Copy the code

The for statement above creates two lexical fields: the bracket contains the explicit part of the for body lexical field, and the implicit part of the initialization part of the loop. The scope of the implicit lexical part also includes the conditional test part and the iterated part after the loop (i++), as well as the lexical part of the loop.

Example 2

The following if-else test chain demonstrates the effective scope range of x and y:

if x := f(); x == 0 {
fmt.Println(x)
} else if y := g(x); x == y {
fmt.Println(x, y)
} else {
fmt.Println(x, y)
}
fmt.Println(x, y) // compile error: x and y are not visible here
Copy the code

The second if statement is nested inside the first, so the variables that the first if statement conditionally initializes the lexical field declaration are also accessible in the second if. Each branch of the switch statement has a similar lexical rule: the conditional part is an implicit lexical field, and then each is the lexical field of each branch.

Example 3

var cwd string
func init(a) {
cwd, err := os.Getwd() // NOTE: wrong!
iferr ! =nil {
log.Fatalf("os.Getwd failed: %v", err)
}
log.Printf("Working directory = %s", cwd)
}
Copy the code

Although CWD is declared externally, the := statement redeclares CWD and ERR as new local variables. Because the internally declared CWD will mask the externally declared CWD, the code above does not update the package-level declared CWD variable correctly. The global CWD variable is still not properly initialized, and the seemingly normal log output makes the BUG even more insidious.