Menu
CoddyTech

Экспортируемые и неэкспортируемые элементы

Часть раздела Логика и управление потоком путешествия по 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 выдаст ошибку компиляции, потому что этот идентификатор не виден за пределами своего пакета.

challenge icon

Задание

Легко

Исправьте проблемы с видимостью в пакете 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")

Ваша задача:

  1. Разобрать первый входной параметр, разделив его по вертикальным чертам, чтобы получить отдельные определения пакетов
  2. Для каждого определения пакета разделить его по двоеточиям, чтобы получить имя пакета и его идентификаторы
  3. Для каждого определения идентификатора разделить его по двоеточиям, чтобы получить имя идентификатора, тип и предполагаемую видимость
  4. Создать функцию с именем fixIdentifierName, которая принимает имя идентификатора и предполагаемую видимость и возвращает исправленное имя:
    • Если видимость равна "public", убедиться, что идентификатор начинается с заглавной буквы
    • Если видимость равна "private", убедиться, что идентификатор начинается со строчной буквы
  5. Вывести заголовок анализа пакетов: "=== PACKAGE VISIBILITY ANALYSIS ==="
  6. Для каждого пакета вывести информацию о пакете:
    • "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
	
	// Разберите определения пакетов
	
	// Выведите результаты анализа пакетов
	
	// Разберите попытки доступа
	
	// Выведите результаты проверки доступа
	
	// Рассчитайте и выведите сводную статистику
	
	// Выведите рекомендации
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и управление потоком

Потренируйтесь самостоятельно: Онлайн-компилятор Go