我用 Rust 写了一个 Hello World

入职第一天,老板要试一下我的水平,于是给我布置了一个任务,写一个 Hello World吧,但是公司用的是 Rust。

我心想,这不是分分钟的事情嘛,很快程序就写好了:

rust 复制代码
fn main() {
    println!("Hello World!")
}

然后老板说,前端怎么对接你这个接口?啊,你不早说,是写一个接口啊。行吧,那就用 Axum 框架写一个吧,也不是啥难事。虽然不是分分钟,但是三五分钟还是可以搞定的:

rust 复制代码
use axum::Router;
use axum::routing::get;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", async { "Hello World"});

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

然后和老板去回报进度:老板,接口版本的 Hello World 完成了。只见老板眉头一皱:小苏,做一个事情要考虑周全,你这个版本虽然完成了功能,有没有想过安全性呢?给返回 Hello World 加密!

啥!Hello World 也要加密啊,行吧。那就上 AES256-GCM 吧,军规级的,够安全了吧?

rust 复制代码
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
use hex::encode;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(encrypted_hello));
    // 省略没有改变的代码
}

async fn encrypted_hello() -> String {
    let message = b"Hello, World!";
    // 省略三五行加密的模版代码,只是为了说明这里实现了加密
    let ciphertext = cipher.encrypt(nonce, message.as_ref()).unwrap();

    format!("encrypted: {}", encode(&ciphertext))
}

心里想,这回老板应该满意了吧。满心欢喜地找老板交差,仿佛升职加薪迎娶老板女儿的日子马上就要到来了。

给老板演示之后,老板欣然一笑,转而又语重心长地说道:安全是安全了,只是......我的心提到了嗓子眼,只是啥?!

老板停顿了好一会,继续说道:只是你有没有考虑过,Axum 是一个协程框架,你将 CPU 密集的计算放在协程里,会不会阻塞?

天啊,流氓不可怕,啊不,老板不可怕,只怕老板懂技术,似懂非懂最可怕。我就写一个 Hello World 而已啊,需要那么复杂嘛?!行,我接着改。

从老板办公室到工位这一路有点漫长,我的脑子飞快地转动着,Axum 框架是基于 Tokio 协程运行时,Tokio 好像提供了一个 API,可以让将一些密集型的代码放到线程里执行......啊,想到了 task::spawn_blocking()!

rust 复制代码
async fn encrypted_hello() -> String {
    task::spawn_blocking(|| {
        let message = b"Hello, World!";
        // 继续省略
        let ciphertext = cipher.encrypt(nonce, message.as_ref()).unwrap();
        format!("encrypted: {}", encode(&ciphertext))
    }).await.unwrap()
}

走,去老板办公室,我得意地一笑,你难不倒我,你女儿迟早是我的。"老板,我想到办法了,把加密的重活交给 tokio 的线程去执行,就不会阻塞协程了!" 老板,看了一眼我,说道:

"你没看到我和小米同学在谈公事嘛,你先出去!"

我瞟了一眼,小米同学是挺漂亮......感性的......

过了大半个小时,老板来到我的工位前,对我说:"这个版本兼顾了安全和性能,还是不错的,但是......"。老板怎么总是喜欢停顿加但是呢?

"但是,你有没有想过,你把密集型计算委托给 Tokio,如果大家都这么做的话,会导致公共线程池饱和......"。老板,这些是 AI 和你说的嘛?

没办法,继续改,既然不能用公共线程池来做,就要自己启用一个线程,然后和协程之间通过 Channel 进行通信......好像有一个东西叫做 mpsc......我只是写一个 Hello World 啊!天啊,迎娶老板女儿啊,不是西天取经啊。

rust 复制代码
use std::thread;
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
use aes_gcm::aead::Aead;
use axum::Router;
use axum::routing::get;
use hex::encode;
use rand::RngCore;
use rand::rngs::OsRng;
use tokio::sync::{mpsc, oneshot};

struct EncryptTask {
    message: Vec<u8>,
    responder: oneshot::Sender<String>
}

#[tokio::main]
async fn main() {
    let (tx, mut rx) = mpsc::channel::<EncryptTask>(100);

    thread::spawn(move || {
        while let Some(task) = rx.blocking_recv() {
            let key = Key::<Aes256Gcm>::from_slice(&[0u8; 32]);
            let cipher = Aes256Gcm::new(key);

            let mut nonce_bytes = [0u8; 12];
            OsRng.fill_bytes(&mut nonce_bytes);
            let nonce = Nonce::from_slice(&nonce_bytes);

            let ciphertext = cipher.encrypt(nonce, task.message.as_ref()).unwrap();

            let result = format!("nonce: {}, chipher_text: {}", encode(&nonce), encode(&ciphertext));

            let _ = task.responder.send(result);
        }
    });
    let app = Router::new().route("/", get(move || encrypted_hello(tx.clone())));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn encrypted_hello(tx: mpsc::Sender<EncryptTask>) -> String {
    let (resp_tx, resp_rx) = oneshot::channel();
    let task = EncryptTask {
        message: b"Hello World".to_vec(),
        responder: resp_tx,
    };
    tx.send(task).await.unwrap();

    resp_rx.await.unwrap()
}

经过一番折腾,终于完成了。看了一眼窗外,一天过去了,天都黑了。老板和小米同学一前一后走出办公室,正要下班。我抓紧喊了一声,老板我完成了!

老板对我挥了挥手,说道:我想了一下,Hello World 没必要做的那么复杂,你还是改回原来的版本吧.....

相关推荐
液态不合群1 天前
rust程序静态编译的两种方法总结
开发语言·后端·rust
明月看潮生1 天前
青少年编程与数学 02-019 Rust 编程基础 02课题、开始编程
开发语言·算法·青少年编程·rust·编程与数学
rayylee2 天前
Ubuntu也开始锈化了?Ubuntu 计划在 25.10 版本开始引入 Rust Coreutils
linux·ubuntu·rust
Source.Liu2 天前
【PhysUnits】2.2 Scalar<T> 标量元组结构体(scalar/mod.rs)
rust
vivo互联网技术2 天前
FunProxy - 使用 Rust 构建跨平台全链路测试抓包代理工具
软件测试·rust·抓包·代理
@PHARAOH2 天前
WHAT - Rust 静态派发(Static Dispatch)和 动态派发(Dynamic Dispatch)
开发语言·后端·rust
Source.Liu2 天前
【PhysUnits】2 Scalar<T> 标量元组结构体(scalar/mod.rs)
rust
muyouking112 天前
Rust 中 Arc 的深度分析:从原理到性能优化实践
开发语言·性能优化·rust
muyouking112 天前
Rust 与 Golang 深度对决:从语法到应用场景的全方位解析
rust
UestcXiye3 天前
Rust 学习笔记:关于结构体的例题
rust