ПрограммированиеMiddle/Lead Go разработчик

Расскажите об особенностях работы с пакетами (packages) и областями видимости (visibility) в Go. Когда и как стоит использовать экспортируемые и неэкспортируемые объекты?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Go область видимости переменных, функций, структур и методов тесно связана с регистром первой буквы:

  • Имя начинается с заглавной буквы — объект экспортируется за пределы пакета.
  • Имя начинается со строчной буквы — объект доступен только внутри своего пакета.

Файл example.go:

package mypkg var ExportedVar int // доступен в других пакетах var unexportedVar int // только в mypkg

При импорте пакета можно обращаться только к экспортированным объектам.

Best practice:

  • Скрывать имплементационные детали, экспортировать только нужные типы и функции.
  • Для приватных констант/функций использовать строчные имена.

Вопрос с подвохом

Вопрос: "Можно ли экспортировать структуру с неэкспортируемыми полями? Что будет, если попытаться использовать такие поля в другом пакете?"

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

Пример:

// package user type User struct { Name string // Экспортируемое поле age int // Недоступно вне пакета user }

В другом пакете:

u := user.User{Name: "Ivan"} u.age = 42 // Ошибка компиляции: age is not accessible

Примеры реальных ошибок из практики


История

Потеря данных при маршалинге json: В REST API структуру экспортировали, но поля сделали неэкспортируемыми (с маленькой буквы). Как результат, marshal в JSON не включал эти поля, и пользователи API не получали нужную информацию.


История

Не работает доступ к необходимым функциям: Команда вынесла полезные утилиты в отдельный пакет, забыв сделать их имена с большой буквы. Функции остались недоступны, пришлось переделывать интерфейсы.


История

Коллизия имён при автогенерации кода: При генерации кода в одном пакете использовали переменные с одинаковыми именами, отличающимися регистром буквы. Один из скриптов случайно переименовал экспортируемую константу в строчное имя. В результате приложение потеряло глобальный доступ к этой константе, и часть функционала стала недоступной.