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