Упрощение создания приложений с интерфейсом командной строки
Я всегда считаю, что при изучении языка программирования полезно просто начинать разработку приложения с нуля, шаг за шагом. Даже после того, как вы прочитали книгу Язык программирования Rust, вы можете не знать, с чего начать.
В этом руководстве предполагается, что вы хотя бы просмотрели книгу, прежде чем погрузиться в разработку простого приложения с интерфейсом командной строки (CLI) для отображения цены криптовалюты (например, цены биткойнов в долларах США или BTC-USD).
Перед тем, как углубиться в статью, давайте сначала разберемся, предоставив ссылку на репозиторий GitHub, где доступны все исходные коды => https://github.com/sungkim11/crypto-p издателя. Кроме того, я хотел бы показать вам, какое приложение вы будете разрабатывать с использованием Rust, как показано ниже.
Предпосылки
REST API данных о ценах Coinbase
Мы будем использовать Coinbase REST API для получения цены биткойна в долларах США или BTC-USD (https://developers.coinbase.com/api/v2#data-endpoints).
Чтобы вызвать Coinbase REST API, просто скопируйте и вставьте следующий URL-адрес в свой браузер:
https://api.coinbase.com/v2/prices/BTC-USD/spot
Он должен вернуть или загрузить файл response.json
со следующим содержимым в формате JSON для примера, который предоставляет как спотовую цену, так и base-currency
или BTC-USD
.
{ "data":{ "base":"BTC", "currency":"USD", "amount":"40731.94" } }
Ржавые ящики
Прежде чем мы начнем разработку приложения, нам нужно добавить четыре крейта Rust:
- Serde: Это фреймворк для эффективной и универсальной сериализации и десериализации структур данных Rust. Их URL-адрес crates.io — https://crates.io/crates/serde. Serde используется для сопоставления данных JSON со структурами данных Rust или Struct. Он используется для десериализации или преобразования JSON в структуру и сериализации или преобразования структуры в JSON.
Reqwest
: Это HTTP-клиент для Rust. Их URL-адрес crates.io — https://crates.io/crates/reqwest.Reqwest
используется для выполнения HTTPS-запросов к Coinbase REST API.- Токио: Это платформа для написания асинхронных приложений. Их URL-адрес crates.io — https://crates.io/crates/tokio. Tokio нужен для разработки асинхронного приложения.
- Clap: это парсер аргументов командной строки для Rust. Их URL-адрес crates.io — https://crates.io/crates/clap. Clap необходим для разработки приложения с интерфейсом командной строки.
Наконец, Cargo.toml
изменен, чтобы включить четыре ящика следующим образом:
[package] name = "rust-struct" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] serde = { version = "1.0.136", features = ["derive"] } reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1.17.0", features = ["full"] } clap = { version = "3.1.2", features = ["derive"] }
Уроки
В этой статье мы разработаем простое приложение, а затем создадим приложение, чтобы добавить дополнительные функции в последующих уроках:
- Урок 1: Простое асинхронное приложение, которое вызывает Coinbase REST API
- Урок 2. Перенос асинхронного вызова REST API в другую функцию
- Урок 3: Добавление интерфейса командной строки
- Урок 4. Добавление времени, цены покупки криптовалюты, цены продажи криптовалюты и других параметров интерфейса командной строки
Урок 1: Простое асинхронное приложение, которое вызывает Coinbase REST API
Мы разработаем простое асинхронное приложение для вызова REST API Coinbase Price Data с использованием предоставленного URL-адреса, а затем обработаем (т. е. десериализуем) файл JSON в программируемые объекты (т. е. структуры), чтобы мы могли распечатать цены на криптовалюту.
Вы спросите — зачем разрабатывать асинхронное приложение? Это связано с тем, что последующие статьи будут улучшать это приложение, чтобы публиковать цены на криптовалюту в Apache Kafka с использованием ящика rdkafka, поэтому приложение называется Crypto Publisher.
JSON (response.json)
Следующий JSON имеет иерархическую структуру или вложенную структуру, как показано ниже:
{ "data":{ "base":"BTC", "currency":"USD", "amount":"40731.94" } }
Структура ржавчины
Rust Struct поддерживает вложенную структуру, создавая две структуры, в которых тип данных CoinPrice используется для репликации вложенной структуры JSON. Наконец, он реализует Deserialize от Serde для отображения данных JSON в Rust Struct. Самый простой способ создать структуру из файла JSON — перейти к быстрому типу (https://app.quicktype.io/), затем скопировать JSON в качестве источника и указать Rust в качестве цели. Я изменил имя структуры в соответствии со своими потребностями.
#[derive(Serialize, Deserialize, Debug)] pub struct CoinbasePrice { pub data: CoinPrice }#[derive(Serialize, Deserialize, Debug)] pub struct CoinPrice { pub base: String, pub currency: String, pub amount: String, }
Запрос REST API
После того, как мы определили структуры, нам нужно будет сделать запрос REST API. Это делается с помощью конструкции async/.await с использованием среды выполнения Tokio, что отражено в коде как:
- Запрос REST API, который возвращает будущее, а затем ожидает его завершения (Client::new().get(&spot_url).send().await?)
- Разобрать ответ JSON на структуру ConibasePrice, которая возвращает будущее, а затем ждать его завершения (json::‹CoinbasePrice›().await?;)
let resp_spot_price = Client::new().get(&spot_url).send().await?.json::<CoinbasePrice>().await?;
Распечатать цену криптовалюты
Наконец, мы распечатываем цену криптовалюты, используя структуру, а затем возвращаем Ok в конце. Обратите внимание, что структура CoinbasePrice имеет следующую структуру:
CoinbasePrice data base currency amount
Поскольку структура CoinbasePrice назначена resp_spot_price, base = resp_spot_price.data.base.
println!("SPOT: {base}-{currency}: {amount}", base=resp_spot_price.data.base, currency=resp_spot_price.data.currency, amount=resp_spot_price.data.amount); Ok(())
Завершенный код
Наконец, завершенный код приведен ниже, где есть два файла:
- main.rs: Он просто вызывает функцию crypto_publisher в crypto_publisher_1.rs. Обратите внимание на добавление unwrap(), так как fn crypto_publisher() возвращает тип Result.
- crypto_publisher_1.rs
main.rs
crypto_publisher_1.rs
Урок 2. Перенос асинхронного вызова REST API в другую функцию
На этом уроке мы выполним следующее:
- Переместите асинхронный вызов REST API в новую асинхронную функцию, поскольку нам нужно будет вызвать эту функцию три раза, чтобы получить спотовую цену, цену покупки и цену продажи.
- Преобразуйте функцию
crypto_publisher
в функцию, которая вызывает новую асинхронную функцию.
Создайте новую асинхронную функцию
Создается новая асинхронная функция, поэтому мы можем использовать одну и ту же функцию для получения трех цен:
- Спотовая цена
- Цена покупки
- Цена продажи
Следовательно, новая асинхронная функция get_coin_price()
имеет три входных параметра:
- Тип (спот, покупка и продажа)
- Валюта (например, BTS)
- Курсы (например, доллары США)
и возвращает тип результата со строковым значением, которое представлено Ok(resp_price.data.amount)
. Все остальные коды аналогичны предыдущему уроку.
Преобразование функции crypto_publisher
в функцию синхронизации
Функция fn crypto_publisher была упрощена, теперь она просто вызывает get_coin_price(), а затем распечатывает проанализированное возвращаемое значение.
Завершенный код
Наконец, завершенный код приведен ниже, где есть два файла:
- main.rs: Он просто вызывает функцию
crypto_publisher
вcrypto_publisher_2.rs.
crypto_publisher_2.rs
main.rs
:
crypto_publisher_2.rs
:
Урок 3: Добавление интерфейса командной строки
На этом уроке мы выполним следующее:
- Создайте структуру для интерфейса командной строки («CLI») с помощью Clap — простого в использовании, эффективного и полнофункционального анализатора аргументов командной строки.
- Добавить функцию кода CLI
crypto_publisher()
Создать структуру для интерфейса командной строки
У Clap есть API-интерфейс Builder, который использует атрибуты структуры для создания интерфейса командной строки. Следующая структура добавляет два параметра:
- Валюта (например, BTC)
- Курсы (например, доллары США)
Добавить кодовую функцию CLI crypto_publisher()
Мы добавили код CLI в async fn crypto_publisher(), чтобы принимать значения интерфейса командной строки.
let args = Cli::parse(); let currency = &args.currency; let rates = &args.rates;
Завершенный код
Наконец, завершенный код приведен ниже, где есть два файла:
main.rs
: Он просто вызывает функциюcrypto_publisher
вcrypto_publisher_3.rs
.crypto_publisher_3.rs
main.rs
:
crypto_publisher_3.rs
:
Урок 4. Добавление времени, цены покупки криптовалюты, цены продажи криптовалюты и других параметров интерфейса командной строки
Наконец, мы завершаем приложение, объединяя все это. Добавляем следующие функции:
- Добавьте функцию для получения времени
- Добавьте цену покупки и продажи криптовалюты, а также разницу между ценой покупки и ценой продажи.
- Добавьте еще два параметра: частота повторения (или сколько раз должны запускаться приложения) и интервал (или с каким временным интервалом — например: 30 секунд).
Добавить функцию для получения времени
Новая функция get_coin_time()
очень похожа на get_coin_price()
, за исключением того, что у нее нет входных параметров.
Добавьте цену покупки и продажи криптовалюты, а также ценовой спред между ценой покупки и ценой продажи.
Мы улучшаем crypto_publisher()
, добавляя дополнительные вызовы функций для:
- Время
- Цена покупки
- Цена продажи
затем мы собираем все вместе, чтобы распечатать цены для спотовой цены, цены покупки, цены продажи, а также ценового спреда между ценой покупки и ценой продажи.
Добавьте еще два параметра: частоту повторения и интервал повторения
Использование Clap's Builder API, который использует атрибуты структуры для добавления еще двух параметров интерфейса командной строки.
- Интервал (например, 10)
- Частота (например, 30 000 или 30 секунд)
затем мы добавляем цикл для включения двух дополнительных параметров CLI.
Завершенный код
Наконец, завершенный код приведен ниже, где есть два файла:
main.rs
: Он просто вызывает функциюcrypto_publisher
вcrypto_publisher_5.rs
.crypto_publisher_5.rs
main.rs
crypto_publisher_5.rs
:
Надеюсь, эта статья была вам полезна! Спасибо, что прочитали.