Я CEO своей компании MediaRise (компания только начала развиваться), с техническим бэкграундом. Сам люблю писать на разных языках, а вернее пробовать работать с ними. Давно уже слышал о таком языке как Rust.
Rust — это современный системный язык программирования, разработанный для обеспечения высокой производительности и безопасности, особенно при работе с конкурентными процессами. Изначально он был разработан компанией Mozilla, а сейчас поддерживается фондом Rust Foundation. Rust приобретает все большую популярность благодаря своей надежности и эффективности.
Ключевые особенности Rust:
Ключевые особенности Rust:
Безопасность памяти: Rust устраняет общие ошибки программирования, такие как разыменование нулевого указателя и переполнение буфера, благодаря строгой проверке на этапе компиляции, без использования сборщика мусора.
Система владения: Уникальная система владения Rust обеспечивает безопасность памяти без необходимости в сборщике мусора. Она использует систему владения с правилами, которые проверяются компилятором на этапе компиляции.
Конкурентность: Rust упрощает написание конкурентных программ, предотвращая состояния гонки на этапе компиляции благодаря концепциям владения и заимствования.
Производительность: Rust разрабатывался с целью быть таким же быстрым, как и C++, и часто демонстрирует сопоставимую производительность. Он может использоваться для системного программирования, где критична производительность.
Выразительная типовая система: Rust обладает мощной типовой системой, включающей такие возможности, как сопоставление с образцом, алгебраические типы данных и обобщенные типы на основе трейтов, что позволяет писать более выразительный и безопасный код.
Cargo: Rust поставляется с Cargo, системой сборки и менеджером пакетов, который упрощает управление зависимостями, сборку и распространение кода.
Экосистема: Экосистема Rust включает растущую коллекцию библиотек и инструментов, которые помогают разработчикам писать надежный и эффективный код. Официальный реестр пакетов, crates.io, содержит тысячи библиотек с открытым исходным кодом.
Сферы применения Rust:
Системное программирование: Rust идеально подходит для написания операционных систем, драйверов устройств и других низкоуровневых задач, где критичны контроль над оборудованием и производительность.
WebAssembly: Rust может компилироваться в WebAssembly, что позволяет запускать код Rust в веб-браузерах с производительностью, близкой к нативной.
Сетевое программирование: Особенности безопасности и производительность Rust делают его подходящим для написания сетевого ПО, включая веб-серверы и клиенты.
Разработка игр: Производственные характеристики Rust делают его хорошим выбором для разработки игр, где скорость и эффективность критичны.
Командные утилиты: Менеджер пакетов Cargo упрощает создание и распространение командных утилит.
Известные проекты, использующие Rust:
Firefox Quantum: Mozilla использовала Rust для переписывания частей их движка браузера, что привело к значительному улучшению производительности.
Dropbox: Dropbox использует Rust для некоторых своих серверных сервисов.
Cloudflare: Cloudflare использует Rust для нескольких своих производительно критичных сервисов.
Rustlings: Образовательный проект, который помогает изучать Rust через небольшие упражнения.
Комбинация безопасности, производительности и поддержки конкурентности делает Rust привлекательным выбором для многих видов разработки программного обеспечения. Его растущая популярность и активное сообщество гарантируют, что Rust продолжит развиваться и улучшаться.
Думал над идеей, что бы такого реализовать на языке Rust. Мне захотелось написать Telegram-бота, который бы двунаправленно переводил сообщения в чате группы с русского на тайский и наоборот.
Понимаю, что существуют готовые решения, но захотелось создать свой "велосипед" и опробовать новый для себя язык — Rust.
Идея есть, с созданием Telegram-бота проблем нет, но возникла проблема с сервисом, который будет переводить с одного языка на другой. Выбор пал на LibreTranslate. Чтобы использовать его бесплатно, необходимо развернуть приложение на своем сервере. Я так и сделал: установил зависимости и развернул в Docker-контейнере. Проблем не возникло, единственное, что приложение необходимо запускать с флагом: `./run.sh --api-keys`, чтобы можно было получить `api_key`. Подробнее о настройке и получении `api-key` для LibreTranslate можно прочитать на официальном сайте.
Развернув сервер LibreTranslate и получив токен для Telegram-бота, осталось реализовать приложение. Просмотрев официальную документацию по Rust и наработки на GitHub, я начал творить. Установил Rust и Cargo (регистр/менеджер пакетов для Rust). Изучив документацию библиотеки teloxide для создания Telegram-ботов на Rust, написал обработчик для событий сообщений в чате.
#[tokio::main]
async fn main() -> ResponseResult<()> {
dotenv().ok();
env_logger::init();
let token_bot = env::var("TELEGRAM_BOT_KEY").expect("TELEGRAM_BOT_KEY not found");
let bot = teloxide::Bot::new(&token_bot).parse_mode(ParseMode::Html);
// Create a handler for our bot, that will process updates from Telegram
let handler = dptree::entry()
.inspect(|u: Update| {
eprintln!("{u:#?}"); // Print the update to the console with inspect
})
...
.branch(
Update::filter_message()
.branch(
dptree::endpoint(translate_message),
)
);
// Create a dispatcher for our bot
Dispatcher::builder(bot, handler).enable_ctrlc_handler().build().dispatch().await;
Ok(())
}
async fn translate_message(bot: Bot, msg: Message) -> ResponseResult<()> {
if let Some(text) = msg.text() {
match translate(text).await {
Ok(translated_word) => {
bot.send_message(msg.chat.id, translated_word).await?;
}
Err(e) => {
bot.send_message(msg.chat.id, format!("Translation error: {}", e)).await?;
}
}
} else {
bot.send_message(msg.chat.id, "Send me plain text.").await?;
}
Ok(())
}
Далее саму функцию для запроса перевода с API LiberTranslate. Приложение по переводу определяет на каком языке сообщение и переводит на необходимый (ru -> th, th -> ru)
async fn translate(text: &str) -> ResponseResult<String> {
let client = reqwest::Client::new();
let api_translate_url = env::var("API_TRANSLATE_URL").expect("API_TRANSLATE_URL not found");
let api_translate_key = env::var("API_TRANSLATE_KEY").expect("API_TRANSLATE_KEY not found");
let api_detect_url = env::var("API_DETECT_URL").expect("API_DETECT_URL not found");
eprintln!("{text:#?}");
let detect_request = DetectRequest {
q: String::from(text),
api_key: String::from(api_translate_key.clone()),
};
let res = client.post(api_detect_url)
.header("Content-Type", "application/x-www-form-urlencoded")
.form(&detect_request)
.send()
.await?;
let resp_json = res.json::<Vec<DetectResponse>>().await?;
let lang = &resp_json[0].language;
eprintln!("{lang:#?}");
let target_lang = if lang == "ru" { "th" } else { "ru" };
let json_object = json!({
"q": text,
"source": "auto",
"target": target_lang,
"format": "text",
"alternatives": 3,
"api_key": api_translate_key
});
let json_string = serde_json::to_string(&json_object).unwrap();
let res = client.post(api_translate_url)
.body(json_string)
.header("Content-Type", "application/json")
.send()
.await?;
let resp_json = res.json::<TranslateResult>().await?;
let translated_word = resp_json.translatedText;
Ok(translated_word)
}
Результат в Telegram чате
Были проблемы с багами, которые были из-за того, что я использовал старые библиотеки на Rust, когда пытался проблему решить с помощью ChatGPT. Но больше помог живой опыт разработчиков с GitHub, где я смотрел реализацию какого либо функционала: API документация бота, работа с env (файлами окружения), примеры работы с json, отправка rest запросов и также работу конструкции языка.
Я очень рад рабочему приложению, потому что ранее не писал на Rust и это меня вдохновило изучать его дальше. Опытные разработчики наверняка подскажут, как можно оптимизировать код, чему я буду очень рад.
Осталось сбилдить приложение и запустить его в режиме демона на сервере
Настройка systemd
Соберите ваше приложение с помощью команды:
cargo build --release
Создайте файл юнита для systemd
. Например, создадим файл /etc/systemd/system/translate_bot.service
[Unit]
Description=Translate Bot
After=network.target
[Service]
ExecStart=/path/to/your/application
Restart=always
User=yourusername
Group=yourgroupname
Environment=/path/to/your/.env
WorkingDirectory=/path/to/your/application/directory
[Install]
WantedBy=multi-user.target
Перезагрузите конфигурацию systemd
, чтобы он узнал о новом сервисе:
sudo systemctl daemon-reload
Запустите сервис:
sudo systemctl start translate_bot
Убедитесь, что сервис запущен и работает:
sudo systemctl status translate_bot
Чтобы ваш сервис автоматически запускался при старте системы, выполните команду:
sudo systemctl enable rust_service
Ваше приложение на Rust будет работать как системный сервис, управляемый systemd
. Вы можете контролировать его с помощью стандартных команд systemd
, таких как start
, stop
, restart
, и status
.
P.S. Хотел бы также решить проблему с env файлами, чтобы доступ к ним был в функции из main.
Далее в планах: я бы хотел реализовать обработку события, если в чате появится новый user (а также ливнет). User может выбрать язык, на котором бы он хотел получать перевод. Сами юзеры и их настройки будут храниться в базе PostgreSQL
Всем спасибо за внимание! Исходники выложил на GitHub.
Комментарии (24)
Lev3250
21.07.2024 15:48+8Я CEO своей компании MediaRise (компания только начала развиваться)
Hidden text
Akuma
21.07.2024 15:48+4Rust для перекладывания json-ов - это ужасный выбор. Чисто как попробовать можно, но довольно бессмысленно.
sdramare
21.07.2024 15:48А зачем здесь раст если 99.999999% времени приложения просто будет ждать вот здесь ответа
let res = client.post(api_detect_url)
Такое приложение можно было бы написать хоть на питоне, при этом вышло бы в 10 раз быстрее и в 10 раз лаконичней без заметной потери в производительности.
И зачем было брать
env_logger::init();
Если вы потом всеравно напрямую пишите в io::stderr типа
eprintln!("{lang:#?}");
И почему туда летят просто отладочные сообщения?
Не надо явно создавать json строки, http клиент в расте(request) имеет метод .json(&data) в билдере, надо фичу json включить для этого.
MountainGoat
21.07.2024 15:48Rust над Питоном в таких случаях выбирать есть смысл в одной ситуации: планируется версия для Android или WebAsm. У Питона с этим до сих пор хреновенько, по сравнению с ним Rust входит с ноги. Ну или хочется скомпилированную программу под десктоп, чтоб не совсем уж кто хочет ковырялся в твоих исходниках.
sdramare
21.07.2024 15:48Ну питон я привел как пример языка с низкой производительностью, а так можно взять любой язык с GC и для Android и для декстопа и получить не хуже перфоманс и гораздо дешевле стоимость разработки.
Digkill
21.07.2024 15:48я написал бота за 1 день, до этого ни разу не используя Rust. Поэтому ошибок куча, я хотел просто попробовать rust в деле, но с такой токсичной аудиторией как в помойке хабра, лучше сюда статьи никогда не выкладывать.
Dartess
21.07.2024 15:48Согласен, лучше!
Ещё можно комментарии не писать, ну её, эту аудиторию.
AlexZyl
21.07.2024 15:48Автору так нетерпелось поругать хабр что он аж свою консерву двенадцатиледней давности вскрыл.
@moderatorDigkill
21.07.2024 15:48ну это уже все знают, в хабре самые никчемные сидят, помойка рунета, все адекватные уже давно на dev и редите
sdramare
21.07.2024 15:48Так а какой реакции вы ожидали на такую статью? "Чел, ты молодец, что попробовал что-то новое для себя, круто что тебя это вдохновляет"? Ну даже в этом случае, лучше было бы тогда сделать упор на персональный опыт, типа "вот я всю жизнь писал на php, а теперь попробовал сделать протенькую программу на расте, вот что мне понравилось, а вот что нет".
ivanuzzo
21.07.2024 15:481 день ? Я перед тем как писать на Rust месяц только на документацию потратил, прошел через боль - настолько было тяжело после динамических языков типа JS и Python. Вы даже не попробовали Раст, считайте, а уже бросились писать статью. Могли бы пойти более простым путем - попросить chatGPT написать код для вас и написать статью об этом.
необязательно свой первый опыт тут же тащить на хабр - такие статьи только засоряют эфир. Вы бы лучше развили свой проект, столкнулись бы с рядом трудностей и после этого написали бы статью, как вы эффективно решили какую-то проблему - такая статья пригодилась бы людям и принесла бы пользу.
Digkill
21.07.2024 15:48уебись об стену, дура с 1 месяцем документации, а я за 1 день рабочий код написал
PeopleMax
Интересно, какой в итоге язык будет более популярным, rust или go. Я почему то думаю что go. Так сказать у go маркетинг более развит
Ksoo
Довольно предсказуемо на данном этапе, golang будет оставаться более популярен, из-за меньшего порога входа и достаточной универсальности.
AdVv
Rust имеет уникальные возможности. А что уникального может предложить golang ?
taslismanfr
Время и деньги. Если rust сможет решать задачи бизнеса минимизируя эти параметры лучше чем go, то тогда он станет популярнее.
sdramare
минимальный порог вхождения, высокую производительность и очень удобную асинхроную модель.
JekaMas
Go. Он проще. Ровно так же у простых языков популярность всегда выше.
sdramare
Еще важным фактором является компания-локомотив, которая будет продвигать язык через свои продукты. У C# есть MS, у Go гугл, у Kotlin JetBrains и т.д. А раст все свои годы существует как интересный язык, у которого за плечами ни больших проектов, ни вакансий.
JekaMas
Вакансии - это да. Выбор их стал лучше, но всё ещё очень ограничен. Хотя производительность на расте, по ощущениям, на попядок выше гошки в типовых задачах.
sdramare
В типовых задачах(CRUD с перекладыванием JSON), практически никогда язык не будет боттлнеком на фоне чтения из базы, редиса, кафки и api коллов к другим сервисам. Зато время разработки на расте, особенно на этапе MVP, занимает в разы, а то и на порядок больше, чем на языках с GC. Я уже не говорю про то, что в момент, когда у вас в коде появится что-то типа Arc<Mutex<HashMap<_>>>(а оно появится), о перфомансе в принципе можно будет перестать говорить.
lorc
Я не думаю что rust и go нацелены на одну и ту же нишу. Rust - это попытка заменить в С в задачах системного программирования. Его поддержку уже втянули в Linux kernel и например в OP-TEE.
Golang - же в ядре никогда не будет поддерживаться. У него совершенно иная ниша - прикладной софт.
Они не конкурируют между собой, поэтому вопрос что будет более популярным - не имеет особого смысла. Это как сравнивать по популярности картошку и авокадо. Да, картошка безусловно популярнее. Но вы не будете класть картошку в блюда, где по рецепту должен быть авокадо.