Хотя то, что мы сделали в этой главе, может показаться довольно простым, важно помнить, что эти концепции являются общими для каждого будущего проекта Crystal, который вы будете создавать. Правильный дизайн приложения, как с точки зрения организационной структуры, так и с точки зрения самого кода, является важной частью разработки удобочитаемых, тестируемых и сопровождаемых приложений.
5. Операции ввода/вывода
В этой главе будет подробно рассмотрено CLI-приложение, о котором говорилось в предыдущей главе, с акцентом на операции ввода/вывода (IO). В ней будут рассмотрены следующие темы:
• Поддержка терминального ввода-вывода, такого как STDIN/STDOUT/STDERR
• Поддержка дополнительного ввода-вывода
• Тестирование производительности
• Объяснение поведения ввода-вывода
К концу этой главы у вас должно быть общее представление об операциях ввода-вывода, в том числе о том, как их использовать и как они себя ведут. С помощью этих концепций вы сможете создавать интерактивные, эффективные потоковые алгоритмы, которые могут быть использованы в различных приложениях. Знание того, как работает IO, также поможет вам понять более сложные концепции, которые будут рассмотрены в следующих главах, таких как
Технические требования
Для выполнения кода, описанного в этой главе, вам потребуется следующее программное обеспечение:
• Рабочая установка Crystal
• Рабочая установка jq
• Средство измерения использования памяти, например https://man7.org/linux/man-pages/man1/time.1.html с параметром -v
Инструкции по настройке Crystal приведены в
Все примеры кода, использованные в этой главе, можно найти в папке Chapter 5 на GitHub: https://github.com/PacktPublishing/Crystal-Programming/tree/main/Chapter05.
Поддерживающий терминальный ввод/вывод
В предыдущей главе мы остановились на нашем типе процессора, имеющем метод def process(input : String) : String
, который преобразует входную строку, обрабатывает ее с помощью jq, а затем преобразует и возвращает выходные данные. Затем мы вызываем этот метод со статическим вводом. Однако CLI-приложение не очень полезно, если его нужно перекомпилировать каждый раз, когда вы хотите изменить входные данные.
Более правильный способ справиться с этим - использовать терминальный ввод-вывод, а именно Standard In(STDIN)
, Standard Out (STDOUT)
и Standard Error (STDERR)
. Это позволит нам использовать данные, выводить данные и выводить ошибки соответственно. Фактически, вы уже используете стандартный вывод, даже не подозревая об этом! Метод Crystal puts
записывает переданное ему содержимое в стандартный вывод, за которым следует перевод строки. Тип STDOUT наследуется от абстрактного типа ввода-вывода, который также определяет метод puts
для экземпляра ввода-вывода. В принципе, это позволяет вам делать то же самое, что и puts верхнего уровня, но для любого ввода-вывода. Например, обратите внимание, что эти два варианта puts
дают один и тот же результат:
puts "Hello!" # => Hello!
STDOUT.puts "Hello!" # => Hello!
Но подождите, что такое IO? Технически в Crystal IO — это все, что наследуется от абстрактного типа IO
.
Однако на практике ввод/вывод обычно представляет собой что-то, что может записывать и/или считывать данные, например файлы или тела HTTP-запроса/ответа. IO также обычно реализуется таким образом, что не все читаемые/записываемые данные должны находиться в памяти одновременно, чтобы поддерживать «потоковую передачу» данных. Пользовательский IO также может быть определен для более специализированных случаев использования.
В нашем контексте типы STDIN
, STDOUT
и STDERR
фактически являются экземплярами IO::FileDescriptor.