Область видимости (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