Что создают и для чего используются явные блоки кода (фигурные скобки) внутри функции в Go?

Ответ

Да, можно. Такой блок создает новую лексическую область видимости (lexical scope).

Основное правило: переменные, объявленные внутри этого блока, видны только в его пределах и "затеняют" (shadow) переменные с такими же именами из внешней области видимости.

func main() {
    x := 10
    fmt.Println("Внешний x:", x) // -> Внешний x: 10

    {
        y := 20
        x := 99 // Эта переменная 'x' затеняет внешнюю. Она новая и локальная.
        fmt.Println("Внутренний x:", x) // -> Внутренний x: 99
        fmt.Println("Внутренний y:", y) // -> Внутренний y: 20
    }

    // fmt.Println(y) // Ошибка компиляции: y не определена в этой области видимости
    fmt.Println("Снова внешний x:", x) // -> Снова внешний x: 10
}

Основные сценарии использования:

  1. Ограничение "жизни" переменных: Полезно для временных переменных, которые нужны для небольшого участка логики и не должны "засорять" остальную часть функции. Это повышает читаемость и снижает риск ошибок.

  2. Управление ресурсами с defer: Можно ограничить действие defer локальным блоком, чтобы ресурс освободился сразу после использования, а не в конце всей функции.

    {
        file, err := os.Open("temp.txt")
        if err != nil { /* ... */ }
        defer file.Close() // Сработает при выходе из этого блока {}
    
        // работа с файлом...
    }
    // Здесь файл уже закрыт.
  3. Переиспользование имен переменных: Позволяет использовать короткие, стандартные имена (вроде err, n, buf) в разных, не связанных друг с другом логических блоках внутри одной большой функции.

Этот же механизм областей видимости используется в управляющих конструкциях, таких как if, for и switch, когда переменная объявляется в их условии: if err := doSomething(); err != nil { ... }.