Объединение файлов
Создайте CLI, объединяющий CSV-файлы из заданного каталога в выходной CSV. Обязательные параметры: --input, --output, --key, --workers и --max-file-size. Выходной путь должен находиться вне входного дерева; символические ссылки не обходятся. CSV-разделитель — запятая, формат кавычек соответствует стандартному CSV. Первая строка каждого непустого файла — заголовок; заголовки должны иметь одинаковые имена и порядок во всех файлах. Несовпадение схемы — фатальная ошибка: выходной файл не должен заменяться частичным содержимым.
Аргумент --key задаёт имя непустого столбца уникальности. Повтор ключа в разных файлах или строках дедуплицируется: сохраняется первая строка по лексикографическому относительному пути файла, затем по номеру строки. Выход включает единственный заголовок и уникальные строки в порядке ключа по возрастанию. Пустые CSV пропускаются, но файл только с заголовком учитывается для проверки схемы. Строка неверной длины или пустой ключ диагностируется с файлом и строкой, пропускается, и делает результат частичным.
Ограничьте workers положительным числом; ограничьте одновременно открытые файлы тем же числом. Аргумент --max-unique задаёт положительный жёсткий предел числа уникальных ключей, хранимых в памяти. Читайте CSV построчно, а очередь файлов ограничьте буфером не более workers элементов. Поскольку итог сортируется, память для строк результата ограничена --max-unique и документируется как O(--max-unique × средний размер строки). При достижении предела новые неизвестные ключи пропускаются с диагностикой, результат помечается частичным и код возврата ненулевой; уже виденные ключи дедуплицируются обычным образом. Применяйте context.Context к обходу, чтению и ожиданию работников; CLI создаёт контекст с обработчиком SIGINT и SIGTERM. При отмене прекратите задания, дождитесь работников, закройте файлы и удалите временный выход; неполный выход не должен становиться итоговым. После полного или частичного завершения корректных входов атомарно публикуйте выход и возвращайте ненулевой код при построчных ошибках. Все результаты и диагностики детерминированы. Тестируйте отмену и конкуренцию с race detector.
Структура программы
Разместите обход и CSV-чтение в internal/csvfiles, проверку совместимости схем и выбор строки по ключу в internal/consolidate, атомарную публикацию — в отдельной файловой операции. main.go создаёт context, работников и каналы и управляет отменой. Правила дедупликации не должны зависеть от CLI; зависимости направьте к данным, не создавая циклов.