18. Понимание блоков и области видимости в Go

Python

Привет всем, меня зовут Мин.

Во время самостоятельного изучения Golang я написал подробные учебные заметки и разместил их в своем личном общедоступном аккаунте WeChat «Время программирования Go». вы только изучаете язык Go, уделяйте ему внимание, учитесь и развивайтесь вместе.

Мой онлайн-блог:golang.iswbm.comМой Github: github.com/iswbm/GolangCodingTime


Поскольку Go использует лексическую область видимости, а лексическая область видимости зависит от блоков операторов. Итак, говоря о области действия, вам нужно сначала понять, что такое блок операторов в Go?

1. Явный блок и неявный блок

С точки зрения непрофессионала, блок операторов определяется фигурными скобками ({}) содержит ряд утверждений.

Имя, объявленное внутри блока операторов, не может быть доступно внешним блоком. Этот блок определяет область видимости имен, объявленных внутри, то есть область действия.

Блок операторов, заключенный в фигурные скобки, является явным блоком операторов.

В Go также много неявных блоков:

  • Блок основного оператора: включает весь исходный код, соответствующий встроенной области видимости.
  • Блок операторов пакета: включает весь исходный код пакета (пакет может включать несколько файлов в каталоге), соответствующий области действия уровня пакета.
  • Блок оператора файла: включает весь исходный код в файле, соответствующем области действия на уровне файла.
  • For , if, switch и другие операторы сами находятся в своих собственных неявных блоках операторов, соответствующих локальной области видимости.

Первые три пункта легко понять, а четвертый пункт дает несколько примеров

После цикла for переменная i больше не может использоваться

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

После оценки оператора if переменная i больше не может использоваться.

if i := 0; i >= 0 {
    fmt.Println(i)
}

После завершения оператора switch не используется ли снова переменная i?

switch i := 2; i * 4 {
case 8:
    fmt.Println(i)
default:
    fmt.Println(“default”)
}

и каждое предложение оператора switch является неявным блоком операторов

switch i := 2; i * 4 {
case 8:
    j := 0
    fmt.Println(i, j)
default:
    // "j" is undefined here
    fmt.Println(“default”)
}
// "j" is undefined here

2. Понимание четырех областей

Объявление переменной, помимо объявления ее типа, также обращает внимание на позицию объявления.Разные позиции определяют, что у нее разные области видимости.Грубо говоря, это моя переменная, где она доступна и где она находится. недоступно.

В зависимости от того, где они объявлены, области действия можно разделить на следующие четыре типа:

  • Встроенная область видимости: не нужно объявлять ее самостоятельно, все ключевые слова, встроенные типы и функции имеют глобальную область видимости.
  • Область уровня пакета: должна быть объявлена ​​вне функции, и все файлы в пакете могут быть доступны.
  • Область на уровне файла: не нужно объявлять, просто импортируйте. Имя пакета, импортируемого при импорте в файл, доступно только внутри файла
  • Локальная область: объявлена ​​в собственном блоке операторов, включая блоки функций, for, if и другие, или область, образованная пользовательским блоком операторов {}, доступная только в своей собственной локальной области.

Вышеупомянутые четыре области, сверху вниз, варьируются от больших к малым.Для удобства выражения я называю область с большой областью действия областью высокого уровня, а область с малой областью действия - областью низкого уровня. объем.

Для объема, есть несколько моментов, чтобы обобщить:

  • Область низкого уровня с доступом к области высокого уровня
  • Области одного уровня изолированы друг от друга
  • Переменные, объявленные в более низких областях, переопределяют переменные, объявленные в более высоких областях.

Слово предостережения здесь, чтобы не путать объем и время жизни. Область действия оператора объявления соответствует текстовой области исходного кода, это свойство времени компиляции.

Жизненный цикл переменной относится к эффективному периоду времени, в течение которого переменная существует во время работы программы, и на нее могут ссылаться другие части программы в пределах этого временного интервала; это концепция времени выполнения.

3. Статическая область видимости против динамической области действия

По видимости переменных в локальной области видимости, являются ли они статическими или нет, языки программирования можно разделить на следующие два типа:

  • статическая область видимости, например Go
  • Динамическая область видимости, как язык оболочки

Что такое динамическая область, вот демонстрация кода Shell, и вы узнаете

#!/bin/bash
func01() {
    local value=1
    func02
}
func02() {
    echo "func02 sees value as ${value}"
}

# 执行函数
func01
func02

Из кода видно, что значение локальной переменной определено в функции func01. Само собой разумеется, что эта переменная-значение доступна только внутри функции, но, поскольку область действия в оболочке динамическая, ее также можно вызывать в func01 Когда func02, func02 может получить доступ к переменной значения, а область func02 может рассматриваться как локальная область действия локальной области видимости (func01).

Но если вы покинете среду выполнения func01 и поместите ее в глобальную среду или другие функции, func02 не сможет получить доступ к переменной значения.

Таким образом, выход в это время

func02 sees value as 1
func02 sees value as 

Но в Go такой динамической области видимости нет, например, в этом коде, в функции func01, если вы хотите получить переменную name, вы можете найти ее только из области видимости func01 или области видимости более высокого уровня (file- области уровня, области пакета и встроенной области), но не из другой локальной области, которая ее вызывает (поскольку они принадлежат к одному и тому же уровню в иерархии).

import "fmt"

func func01() {
    fmt.Println("在 func01 函数中,name:", name)
}

func main()  {
    var name string = "Python编程时光"
    fmt.Println("在 main 函数中,name:", name)

    func01()
}

Поэтому при выполнении этого кода будет сообщено об ошибке, указывающей, что имя в func01 не было определено.

Справочная статья:изучите golang.com/articles/12…

Руководство по серии

01. Построение среды разработки (Goland & VS Code)

02. Изучите пять методов создания переменных

03. Подробные типы данных:**Целое число и число с плавающей запятой**

04. Подробные типы данных: байт, руна и строка

05. Подробно объясните типы данных: массивы и срезы

06. Подробно объясните типы данных: словари и логические значения

07. Подробно объясните типы данных: указатели

08. Объектно-ориентированное программирование: структуры и наследование

09. Статья для понимания функций в Go

10. Управление потоком языка Go: условный оператор if-else

11. Управление потоком языка Go: оператор выбора switch-case

12. Управление потоком языка Go: оператор цикла for

13. Перейти к управлению языковым потоком: перейти к безусловному переходу

14. Перейти к управлению языковым потоком: отложить отложенный вызов

15. Объектно-ориентированное программирование: интерфейсы и полиморфизм

16. Ключевые слова: В чем разница между make и new?

17. Статья о понимании блоков и области видимости в Go

18. Изучите Go Coroutines: горутины

19. Изучите сопрограммы Go: подробно объясните каналы/каналы

20. Подробное объяснение нескольких классических случаев ошибки взаимоблокировки канала.

21. Изучите сопрограммы Go: группа ожидания

22. Изучите процедуры Go: мьютексы и блокировки чтения-записи

23. Обработка исключений в Go: паника и восстановление

24. Сверхдетальная интерпретация прошлой жизни Go Modules и вводное использование

25. 8 важных знаний об импорте пакетов на языке Go

26. Как открыть исходный код модулей, которые я написал для использования другими?

27. Расскажите об утверждениях типов в Go?

28. Эти пять пунктов помогут вам понять, как использовать select в языке Go.