Экспортируемые и неэкспортируемые элементы
Часть раздела Логика и управление потоком путешествия по 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 [target_package].[identifier_name]: ✗ NOT FOUND"
- Подсчитать и вывести итоговую статистику:
"=== 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 управляет видимостью пакетов, и помогает понять разницу между экспортируемыми и неэкспортируемыми идентификаторами.
Шпаргалка
Go управляет видимостью через соглашения об именовании без явных ключевых слов, таких как public или private.
Экспортируемые идентификаторы начинаются с заглавной буквы и доступны из других пакетов:
// Эти идентификаторы экспортируемые (публичные)
var Name string
func Calculate() int
type Person structНеэкспортируемые идентификаторы начинаются со строчной буквы и доступны только внутри того же пакета:
// Эти идентификаторы неэкспортируемые (приватные)
var age int
func helper() string
type config structПопытка доступа к неэкспортируемым идентификаторам из других пакетов приводит к ошибкам компиляции.
Попробуйте сами
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`Итоги: создание утилиты