Область видимости (scope) определяет набор правил, по которым осуществляется доступ к объявленным переменным, константам и функциям из различных блоков кода.

В Go область видимости можно охарактеризовать двумя параметрами:

  • глобальность/локальность;
  • экспортируемость/неэкспортируемость.

Глобальность/локальность

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

В Go локальные переменные можно объявлять ключевым словом var или короткой нотацией :=.

Рассмотрим пример, который иллюстрирует область видимости локальной переменной:

func main() {
    i := 10
    if i == 10 {
        // изменяем значение переменной i
        i += 5 
        if i == 15 {
            // в этом блоке создаётся новая переменная i, которая
            // перекрывает определённую выше переменную с таким же именем
            // следует избегать таких ситуаций на практике
            i := 7
            fmt.Println(i)
            // область видимости этой переменной ограничена блоком
        }
    }
    fmt.Println(i)
}

Объявленные вне тела функции сущности характеризуются как глобальные и находятся в области видимости всех блоков кода в пакете. То есть глобальные объекты доступны во всех файлах, находящихся в одной директории.

Глобальные переменные нельзя объявлять короткой нотацией :=, необходимо ключевое слово var. Если глобальная переменная не инициализирована, она принимает нулевое значение указанного типа.

// Глобальные константа и переменные.
const program = "Моё приложение"
 
var name string
var ver = "v1.0.0" // инициализируем глобальную переменную
 
func main() {
    // изменяем глобальную переменную name
    name = "Вася"
    fmt.Println("Привет, " + name + "!")
    fmt.Println("Добро пожаловать в", program, ver)
} 

Экспортируемость/неэкспортируемость

Если предыдущее свойство характеризует доступность объекта внутри пакета, то экспортируемость регламентирует доступность из других пакетов. Пакет в Go — это все файлы c расширением .go в одной директории, кроме оканчивающихся на _test.go.

Note

Экспортируемыми могут быть только глобальные сущности.

Экспортируемые переменные, константы и функции определённого пакета доступны из тех пакетов, которые импортируют этот пакет ключевым словом import.

Доступ к экспортируемым объектам осуществляется конструкцией <имя пакета>.<Имя сущности>. Проиллюстрируем на примере Hello, world!:

package main
 
import "fmt"  // импортируем пакет fmt стандартной библиотеки
 
func main() {
    fmt.Println("Hello, world!")
} 

Здесь в функции main программа обращается к пакету стандартной библиотеки fmt, вызывая её экспортируемую функцию Println.

💡💡💡

Как Go определяет, что сущность экспортируемая? Если имя переменной, константы или функции начинается с прописной буквы, то она экспортируемая. Если со строчной, то неэкспортируемая.

К неэкспортируемым сущностям нельзя обратиться за пределами пакета. Этот подход — часть того особенного ООП, который реализует в Go сокрытие данных или инкапсуляцию.

Проиллюстрируем на примере определение экспортируемых и неэкспортируемых объектов.

package contacts
 
// Email 
const Email = "support@example.com" // глобальная экспортируемая константа
 
var support string // глобальная неэкспортируемая переменная
 
// SetSupport устанавливает значение переменной support.
func SetSupport(s string) { // экспортируемая функция
    support = s
}
 
// GetContact возвращает имя и email.
func GetContact() string { // экспортируемая функция
    return fmt.Sprintf("%s <%s>", support, Email)
} 

Если импортировать этот пакет, то будут доступны константа Email, функции SetSupport и GetContact.

package main
 
import (
    "fmt"
    // импортируем пакет из поддиректории internal/contacts
    "myproject/internal/contacts"
)
 
func main() {
    contacts.SetSupport("Служба поддержки")
    fmt.Println(contacts.GetContact())
    fmt.Println("Email:", contacts.Email)
} 

📂 Go | Последнее изменение: 15.08.2024 15:08