Упрощение создания приложений с интерфейсом командной строки

Я всегда считаю, что при изучении языка программирования полезно просто начинать разработку приложения с нуля, шаг за шагом. Даже после того, как вы прочитали книгу Язык программирования 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:

Надеюсь, эта статья была вам полезна! Спасибо, что прочитали.