Экспортируемые и неэкспортируемые элементы
Часть раздела Логика и управление потоком путешествия по GO на Coddy. Урок 52 из 68.
В Go видимость идентификаторов (переменных, функций, типов и т. д.) определяется простым соглашением об именовании. Оно определяет, может ли код из других пакетов обращаться к вашим идентификаторам.
Экспортируемые идентификаторы начинаются с заглавной буквы и доступны из других пакетов. Считай их «публичными» — их может использовать любой, кто импортирует твой пакет.
// Они экспортируются (общедоступны)
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Сравнение картИтоги: счетчик частоты слов3Интерфейсы (Основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование интерфейсных типовПустой интерфейсУтверждение типаПереключатель типовИтоги: Фигуры и поведение6Идиоматичный Go: Множества
Идиома множества в GoСоздание множестваДобавление в множествоПроверка наличия элементаУдаление из множестваИтерация по множествуИтоги — Уникальные имена пользователей9Пакеты и область видимости
Что такое пакет?Экспортируемые и неэкспортируемые элементыСоздание простого пакетаПсевдонимы пакетовПустой идентификатор `_`Функция `init`Итоги: создание утилитыПотренируйтесь самостоятельно: Онлайн-компилятор Go