Экспортируемые и неэкспортируемые
Часть раздела Логика и управление потоком путешествия по GO на Coddy. Урок 52 из 68.
В Go видимость идентификаторов (переменных, функций, типов и т. д.) определяется простым соглашением об именовании. От этого зависит, может ли код из других пакетов обращаться к вашим идентификаторам.
Экспортируемые идентификаторы начинаются с заглавной буквы и доступны из других пакетов. Считай их «публичными» — их может использовать любой, кто импортирует твой пакет.
// Они экспортируются (public)
var Name string
func Calculate() int
type Person structНеэкспортируемые идентификаторы начинаются со строчной буквы и доступны только в пределах того же пакета. Они являются «приватными» для вашего пакета.
// Они не экспортируются (приватные)
var age int
func helper() string
type config structЭто соглашение об именовании — способ Go управлять доступом без необходимости использовать ключевые слова вроде public или private. Если попытаться использовать неэкспортируемый идентификатор из другого пакета, Go выдаст ошибку компиляции, потому что этот идентификатор не виден за пределами своего пакета.
Задание
ЛегкоИсправьте проблемы с видимостью в пакете Go, скорректировав соглашение об именовании экспортируемых и неэкспортируемых идентификаторов. Вы будете работать с имитацией ситуации с несколькими пакетами, где некоторые идентификаторы названы неправильно, из-за чего возникают ошибки компиляции при обращении к ним из других пакетов.
Вы получите два входных значения:
- Строку с определениями пакетов в формате
"package_name:identifier1:type1:visibility1,identifier2:type2:visibility2|package_name:identifier1:type1:visibility1"(например,"utils:helper:function:private,Calculate:function:public|main:name:variable:private,Version:variable:public") - Строку с попытками доступа в формате
"accessing_package.identifier1,accessing_package.identifier2,accessing_package.identifier3"(например,"main.helper,main.Calculate,utils.Version")
Ваша задача:
- Разобрать первый вход, разделив его по вертикальным чертам, чтобы получить определения отдельных пакетов
- Для каждого определения пакета разделить его по двоеточиям, чтобы получить имя пакета и его идентификаторы
- Для каждого определения идентификатора разделить его по двоеточиям, чтобы получить имя идентификатора, тип и предполагаемую видимость
- Создать функцию с именем
fixIdentifierName, которая принимает имя идентификатора и предполагаемую видимость и возвращает исправленное имя:- Если видимость —
"public", убедиться, что идентификатор начинается с заглавной буквы - Если видимость —
"private", убедиться, что идентификатор начинается со строчной буквы
- Если видимость —
- Вывести заголовок анализа пакетов:
"=== PACKAGE VISIBILITY ANALYSIS ===" - Для каждого пакета вывести информацию о нём:
"Package: [package_name]"- Для каждого идентификатора в пакете:
- Если имя идентификатора нужно исправить:
"- [original_name] ([type]) -> [corrected_name] (visibility: [visibility])" - Если имя идентификатора указано правильно:
"- [identifier_name] ([type]) (visibility: [visibility]) ✓"
- Если имя идентификатора нужно исправить:
- Разобрать второй вход, разделив его по запятым, чтобы получить отдельные попытки доступа
- Для каждой попытки доступа разделить её по точкам, чтобы получить пакет, из которого выполняется обращение, и идентификатор, к которому обращаются
- Вывести заголовок проверки доступа:
"=== ACCESS VALIDATION ===" - Для каждой попытки доступа определить, допустимо ли обращение:
- Найти пакет, содержащий идентификатор
- Проверить, начинается ли исправленное имя идентификатора с заглавной буквы (экспортируется ли он)
- Если идентификатор экспортируется:
"[accessing_package] accessing [target_package].[corrected_identifier_name]: ✓ ALLOWED (exported)" - Если идентификатор не экспортируется:
"[accessing_package] accessing [target_package].[corrected_identifier_name]: ✗ DENIED (unexported)" - Если идентификатор не существует:
"[accessing_package] accessing unknown.[identifier_name]: ✗ NOT FOUND"(вывести словоunknownв качестве имени пакета; эта попытка учитывается как запрещённый доступ)
- Подсчитать и вывести сводную статистику:
"=== SUMMARY ===""Total packages analyzed: [number_of_packages]""Total identifiers processed: [total_number_of_identifiers]""Identifiers requiring fixes: [number_of_identifiers_that_needed_fixing]""Access attempts: [number_of_access_attempts]""Allowed accesses: [number_of_allowed_accesses]""Denied accesses: [number_of_denied_accesses]"
- Вывести итоговые рекомендации:
- Если нашлись идентификаторы, требующие исправления:
"Recommendation: Fix identifier naming to follow Go conventions" - Если все идентификаторы указаны правильно:
"All identifiers follow proper Go naming conventions"
- Если нашлись идентификаторы, требующие исправления:
Используйте пакет strings для разделения входных строк, пакет fmt для форматированного вывода и функции обработки строк для проверки и изменения имён идентификаторов. Эта задача показывает, как соглашение об именовании в Go управляет видимостью пакетов, и помогает понять разницу между экспортируемыми и неэкспортируемыми идентификаторами.
Попробуйте сами
package main
import (
"fmt"
"strings"
)
func main() {
// Считайте входные данные
var packageDefinitions string
var accessAttempts string
fmt.Scanln(&packageDefinitions)
fmt.Scanln(&accessAttempts)
// TODO: Напишите свой код ниже
// Создайте функцию fixIdentifierName
// Разберите определения пакетов
// Выведите результаты анализа пакетов
// Разберите попытки доступа
// Выведите результаты проверки доступа
// Рассчитайте и выведите итоговую статистику
// Выведите рекомендации
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Продвинутое управление потоком
Оператор switch с `fallthrough`Выход из вложенных цикловПереход к следующей итерации конкретного циклаОператор `goto`Повторение: расширенное управление циклами4Проект: простой список задач
Настройка проектаДобавление задачи2Структуры и методы
Определение методов для структурПолучатели-значенияПолучатели-указателиВыбор получателейМетоды и функцииПовторение: поведение структур5Карты: подробный разбор
Карты структурУказатели как значения картПроверка карт на nilСравнение картПовторение — счётчик частоты слов8Проект: простой складской учёт
Обзор проектаПроверка запасов3Интерфейсы (основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование типов интерфейсовПустой интерфейсУтверждения типовПереключатель типовПовторение — формы и поведение6Идиоматический Go: множества
Идиома множества в GoСоздание множестваДобавление элементов в множествоПроверка наличия элементаУдаление элемента из множестваПеребор элементов множестваПовторение — уникальные имена пользователей9Пакеты и область видимости
Что такое пакет?Экспортируемые и неэкспортируемыеСоздание простого пакетаПсевдонимы пакетовПустой идентификатор `_`Функция `init`Повторение — создание утилитыПотренируйтесь самостоятельно: Онлайн-компилятор Go