{"id":46030,"date":"2025-07-30T02:13:02","date_gmt":"2025-07-29T18:13:02","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/46030.html"},"modified":"2025-07-30T02:13:02","modified_gmt":"2025-07-29T18:13:02","slug":"rust%e5%be%81%e6%9c%8d%e5%ad%97%e8%8a%82%e8%b7%b3%e5%8a%a8%ef%bc%9a%e9%ab%98%e5%b9%b6%e5%8f%91%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%ae%9e%e6%88%98","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/46030.html","title":{"rendered":"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218"},"content":{"rendered":"<h3 style=\"background-color:transparent\">Rust \u7528\u4e8e\u5b57\u8282\u8df3\u52a8\u7ea7\u670d\u52a1\u5668<\/h3>\n<p>\u4ee5\u4e0b\u662f Rust \u7528\u4e8e\u5b57\u8282\u8df3\u52a8\u7ea7\u670d\u52a1\u5668\u540e\u53f0\u5f00\u53d1\u7684\u5b9e\u7528\u793a\u4f8b\u5206\u7c7b\u4e0e\u6838\u5fc3\u4ee3\u7801\u7247\u6bb5&#xff0c;\u6db5\u76d6\u9ad8\u5e76\u53d1\u3001\u5206\u5e03\u5f0f\u3001\u7f51\u7edc\u901a\u4fe1\u7b49\u5173\u952e\u573a\u666f&#xff1a;<\/p>\n<h4 style=\"background-color:transparent\">\u7f51\u7edc\u901a\u4fe1<\/h4>\n<p>\/\/ \u5f02\u6b65TCP\u670d\u52a1\u5668&#xff08;tokio&#xff09;<br \/>\nuse tokio::net::TcpListener;<br \/>\nasync fn tcp_server() {<br \/>\n    let listener &#061; TcpListener::bind(&#034;127.0.0.1:8080&#034;).await.unwrap();<br \/>\n    while let Ok((socket, _)) &#061; listener.accept().await {<br \/>\n        tokio::spawn(async move {<br \/>\n            let (mut reader, mut writer) &#061; socket.into_split();<br \/>\n            tokio::io::copy(&amp;mut reader, &amp;mut writer).await.unwrap();<br \/>\n        });<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ HTTP\u63a5\u53e3&#xff08;actix-web&#xff09;<br \/>\nuse actix_web::{get, App, HttpServer, Responder};<br \/>\n#[get(&#034;\/api\/v1\/feed&#034;)]<br \/>\nasync fn fetch_feed() -&gt; impl Responder {<br \/>\n    format!(&#034;{:?}&#034;, get_recommendations().await)<br \/>\n}<\/p>\n<h4>\u9ad8\u5e76\u53d1\u5904\u7406<\/h4>\n<p>\/\/ \u65e0\u9501\u961f\u5217&#xff08;crossbeam&#xff09;<br \/>\nuse crossbeam::queue::ArrayQueue;<br \/>\nlet queue &#061; ArrayQueue::new(1000);<br \/>\nstd::thread::scope(|s| {<br \/>\n    s.spawn(|| queue.push(1).unwrap());<br \/>\n    s.spawn(|| queue.pop().unwrap());<br \/>\n});<\/p>\n<p>\/\/ \u5f02\u6b65\u4efb\u52a1\u6c60&#xff08;rayon&#xff09;<br \/>\nuse rayon::prelude::*;<br \/>\nlet results: Vec&lt;_&gt; &#061; (0..10000).into_par_iter()<br \/>\n    .map(|i| i * i)<br \/>\n    .collect();<\/p>\n<h4 style=\"background-color:transparent\">\u6570\u636e\u5b58\u50a8<\/h4>\n<p>\/\/ Redis\u64cd\u4f5c&#xff08;redis-rs&#xff09;<br \/>\nlet client &#061; redis::Client::open(&#034;redis:\/\/127.0.0.1\/&#034;).unwrap();<br \/>\nlet mut con &#061; client.get_connection().unwrap();<br \/>\nredis::cmd(&#034;SET&#034;).arg(&#034;key&#034;).arg(&#034;value&#034;).execute(&amp;mut con);<\/p>\n<p>\/\/ \u6570\u636e\u5e93\u67e5\u8be2&#xff08;sqlx&#xff09;<br \/>\nlet rec: (i64,) &#061; sqlx::query_as(&#034;SELECT $1&#034;)<br \/>\n    .bind(150_i64)<br \/>\n    .fetch_one(&amp;pool)<br \/>\n    .await?;<\/p>\n<h4>\u6027\u80fd\u4f18\u5316<\/h4>\n<p>\/\/ SIMD\u52a0\u901f&#xff08;std::simd&#xff09;<br \/>\nuse std::simd::f32x4;<br \/>\nlet a &#061; f32x4::splat(3.0);<br \/>\nlet b &#061; f32x4::from_array([1.0, 2.0, 3.0, 4.0]);<br \/>\nlet c &#061; a &#043; b;<\/p>\n<p>\/\/ \u5185\u5b58\u6c60&#xff08;bumpalo&#xff09;<br \/>\nlet bump &#061; bumpalo::Bump::new();<br \/>\nlet val &#061; bump.alloc(&#034;value&#034;);<\/p>\n<h4 style=\"background-color:transparent\">\u5b89\u5168\u9632\u62a4<\/h4>\n<p>\/\/ \u5bc6\u7801\u54c8\u5e0c&#xff08;argon2&#xff09;<br \/>\nlet salt &#061; rand::thread_rng().gen::&lt;[u8; 32]&gt;();<br \/>\nlet hashed &#061; argon2::hash_encoded(&#034;password&#034;.as_bytes(), &amp;salt, &amp;Config::default()).unwrap();<\/p>\n<p>\/\/ JWT\u9a8c\u8bc1&#xff08;jsonwebtoken&#xff09;<br \/>\nlet token &#061; encode(&amp;Header::default(), &amp;claims, &amp;EncodingKey::from_secret(&#034;secret&#034;.as_ref()))?;<\/p>\n<p>\u5b8c\u6574\u4ee3\u7801\u5e93\u5efa\u8bae\u53c2\u8003&#xff1a;<\/p>\n<ul>\n<li>\u5b57\u8282\u8df3\u52a8\u5f00\u6e90\u9879\u76eeMonio\u7684Rust\u7ec4\u4ef6<\/li>\n<li>\u5b98\u65b9\u5f02\u6b65\u8fd0\u884c\u65f6tokio\u6848\u4f8b\u96c6<\/li>\n<li>\u4e91\u539f\u751f\u6846\u67b6volo\u5b9e\u8df5<\/li>\n<\/ul>\n<p>&#xff08;\u6ce8&#xff1a;\u4ee5\u4e0a\u4e3a\u793a\u4f8b\u7247\u6bb5&#xff0c;\u5b9e\u9645\u751f\u4ea7\u73af\u5883\u9700\u914d\u5408\u9519\u8bef\u5904\u7406\u3001\u65e5\u5fd7\u76d1\u63a7\u7b49\u5b8c\u6574\u5b9e\u73b0&#xff09;<\/p>\n<h3 style=\"background-color:transparent\">Rust\u4e91\u539f\u751f\u6846\u67b6Volo<\/h3>\n<p>\u4ee5\u4e0b\u662f\u5173\u4e8eRust\u4e91\u539f\u751f\u6846\u67b6Volo\u7684\u5b9e\u8df5\u793a\u4f8b\u6574\u7406&#xff0c;\u6db5\u76d6\u57fa\u7840\u5230\u8fdb\u9636\u7684\u5e94\u7528\u573a\u666f\u3002\u7531\u4e8e\u5b8c\u6574\u5217\u51fa100\u4e2a\u793a\u4f8b\u7bc7\u5e45\u8fc7\u957f&#xff0c;\u8fd9\u91cc\u63d0\u4f9b\u5206\u7c7b\u6846\u67b6\u548c\u4ee3\u8868\u6027\u6848\u4f8b&#xff0c;\u540e\u7eed\u53ef\u57fa\u4e8e\u6b64\u6269\u5c55&#xff1a;<\/p>\n<h4 style=\"background-color:transparent\">\u57fa\u7840\u901a\u4fe1\u793a\u4f8b<\/h4>\n<p>HTTP\u670d\u52a1\u642d\u5efa<\/p>\n<p>use volo_http::{Server, Request, Response};<\/p>\n<p>#[volo::main]<br \/>\nasync fn main() {<br \/>\n    Server::new()<br \/>\n        .get(&#034;\/hello&#034;, |_req: Request| async {<br \/>\n            Response::builder().body(&#034;Hello Volo!&#034;.into())<br \/>\n        })<br \/>\n        .run(&#034;127.0.0.1:8080&#034;)<br \/>\n        .await;<br \/>\n}<\/p>\n<p>gRPC\u670d\u52a1\u7aef<\/p>\n<p>use volo_grpc::server::{Server, ServiceBuilder};<\/p>\n<p>#[derive(volo_grpc::Service)]<br \/>\nstruct Greeter;<br \/>\nimpl volo_grpc::Service for Greeter {<br \/>\n    async say_hello(&amp;self, req: Request&lt;HelloRequest&gt;) -&gt; Result&lt;Response&lt;HelloReply&gt;&gt; {<br \/>\n        Ok(Response::new(HelloReply {<br \/>\n            message: format!(&#034;Hello {}&#034;, req.name),<br \/>\n        }))<br \/>\n    }<br \/>\n}<\/p>\n<p>#[volo::main]<br \/>\nasync fn main() {<br \/>\n    Server::new()<br \/>\n        .add_service(ServiceBuilder::new(Greeter).build())<br \/>\n        .serve(&#034;127.0.0.1:50051&#034;)<br \/>\n        .await;<br \/>\n}<\/p>\n<h4>\u4e91\u539f\u751f\u7ec4\u4ef6\u96c6\u6210<\/h4>\n<p>Kubernetes\u5065\u5eb7\u68c0\u67e5<\/p>\n<p>use volo::healthz::{Healthz, HealthzResponse};<\/p>\n<p>#[volo::service]<br \/>\nimpl Healthz for MyService {<br \/>\n    async fn check(&amp;self) -&gt; Result&lt;HealthzResponse&gt; {<br \/>\n        Ok(HealthzResponse::healthy())<br \/>\n    }<br \/>\n}<\/p>\n<p>Prometheus\u6307\u6807\u66b4\u9732<\/p>\n<p>use volo_metrics::prometheus::Counter;<\/p>\n<p>let counter &#061; Counter::new(&#034;requests_total&#034;, &#034;Total requests&#034;).unwrap();<br \/>\ncounter.inc();<\/p>\n<h4 style=\"background-color:transparent\">\u9ad8\u7ea7\u7279\u6027\u793a\u4f8b<\/h4>\n<p>\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6<\/p>\n<p>use volo::middleware::{Middleware, Next};<br \/>\nuse volo_http::Request;<\/p>\n<p>struct LogMiddleware;<br \/>\nimpl Middleware&lt;Request&gt; for LogMiddleware {<br \/>\n    async fn call(&amp;self, req: Request, next: Next&lt;Request&gt;) -&gt; Result&lt;Response&gt; {<br \/>\n        println!(&#034;Request: {:?}&#034;, req);<br \/>\n        next.call(req).await<br \/>\n    }<br \/>\n}<\/p>\n<p>\u5f02\u6b65\u4efb\u52a1\u961f\u5217<\/p>\n<p>use volo_broker::RedisBroker;<\/p>\n<p>#[volo::main]<br \/>\nasync fn main() {<br \/>\n    let broker &#061; RedisBroker::new(&#034;redis:\/\/localhost&#034;);<br \/>\n    broker.publish(&#034;tasks&#034;, &#034;task_data&#034;).await;<br \/>\n}<\/p>\n<h4>\u751f\u4ea7\u7ea7\u5b9e\u8df5<\/h4>\n<p>\u914d\u7f6e\u4e2d\u5fc3\u96c6\u6210<\/p>\n<p>use volo_config::apollo::ApolloConfig;<\/p>\n<p>let config &#061; ApolloConfig::new(&#034;http:\/\/config-server&#034;)<br \/>\n    .namespace(&#034;application&#034;)<br \/>\n    .get(&#034;database.url&#034;)<br \/>\n    .await;<\/p>\n<p>\u5206\u5e03\u5f0f\u8ffd\u8e2a<\/p>\n<p>use volo_tracing::{init_tracer, Span};<\/p>\n<p>init_tracer(&#034;my-service&#034;).unwrap();<br \/>\nlet span &#061; Span::new(&#034;request_processing&#034;);<\/p>\n<h4 style=\"background-color:transparent\">\u6269\u5c55\u5efa\u8bae<\/h4>\n<li>\u6570\u636e\u5e93\u64cd\u4f5c&#xff1a;\u7ed3\u5408SQLx\u6216Diesel\u5b9e\u73b0CRUD<\/li>\n<li>\u6d88\u606f\u961f\u5217&#xff1a;\u96c6\u6210Kafka\u6216NATS\u7684Producer\/Consumer<\/li>\n<li>Auth\u6a21\u5757&#xff1a;JWT\u9a8c\u8bc1\u4e2d\u95f4\u4ef6\u5b9e\u73b0<\/li>\n<li>\u6d4b\u8bd5\u5957\u4ef6&#xff1a;\u9488\u5bf9gRPC\u670d\u52a1\u7684mock\u6d4b\u8bd5<\/li>\n<li>\u6027\u80fd\u4f18\u5316&#xff1a;\u8fde\u63a5\u6c60\u914d\u7f6e\u4e0e\u538b\u6d4b\u6848\u4f8b<\/li>\n<p>\u5b8c\u6574\u793a\u4f8b\u5efa\u8bae\u53c2\u8003Volo\u5b98\u65b9\u6587\u6863\u7684examples\u76ee\u5f55&#xff08;https:\/\/github.com\/volo-rs\/volo&#xff09;&#xff0c;\u5176\u4e2d\u5305\u542b\u5404\u7c7b\u573a\u666f\u7684\u8be6\u7ec6\u5b9e\u73b0\u3002\u5b9e\u9645\u5f00\u53d1\u65f6\u53ef\u6839\u636e\u5177\u4f53\u9700\u6c42\u7ec4\u5408\u8fd9\u4e9b\u6a21\u5f0f&#xff0c;\u4f8b\u5982\u5fae\u670d\u52a1\u901a\u4fe1&#043;\u6307\u6807\u76d1\u63a7&#043;\u94fe\u8def\u8ffd\u8e2a\u7684\u590d\u5408\u6848\u4f8b\u3002<\/p>\n<h3>Tokio \u662f Rust \u751f\u6001\u4e2d\u6700\u6d41\u884c<\/h3>\n<p>Tokio \u662f Rust \u751f\u6001\u4e2d\u6700\u6d41\u884c\u7684\u5f02\u6b65\u8fd0\u884c\u65f6\u4e4b\u4e00&#xff0c;\u5e7f\u6cdb\u7528\u4e8e\u6784\u5efa\u9ad8\u6027\u80fd\u7f51\u7edc\u5e94\u7528\u3002\u4ee5\u4e0b\u662f\u7cbe\u9009\u7684 Tokio \u5b9e\u7528\u6848\u4f8b&#xff0c;\u6db5\u76d6\u4ece\u57fa\u7840\u5230\u9ad8\u7ea7\u7684\u591a\u79cd\u573a\u666f\u3002<\/p>\n<h4 style=\"background-color:transparent\">\u57fa\u7840\u5f02\u6b65\u4efb\u52a1<\/h4>\n<p>\u521b\u5efa\u4e00\u4e2a\u7b80\u5355\u7684\u5f02\u6b65\u4efb\u52a1\u5e76\u7b49\u5f85\u5b8c\u6210&#xff1a;<\/p>\n<p>use tokio::task;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let handle &#061; task::spawn(async {<br \/>\n        &#034;Hello from async task&#034;<br \/>\n    });<br \/>\n    println!(&#034;{}&#034;, handle.await.unwrap());<br \/>\n}<\/p>\n<h4>TCP \u670d\u52a1\u5668\u4e0e\u5ba2\u6237\u7aef<\/h4>\n<p>\u5b9e\u73b0\u4e00\u4e2a\u56de\u663e&#xff08;Echo&#xff09;\u670d\u52a1\u5668\u548c\u5ba2\u6237\u7aef&#xff1a;<\/p>\n<p>\/\/ \u670d\u52a1\u5668\u7aef<br \/>\nuse tokio::net::TcpListener;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let listener &#061; TcpListener::bind(&#034;127.0.0.1:8080&#034;).await.unwrap();<br \/>\n    while let Ok((mut socket, _)) &#061; listener.accept().await {<br \/>\n        tokio::spawn(async move {<br \/>\n            let mut buf &#061; [0; 1024];<br \/>\n            let n &#061; socket.read(&amp;mut buf).await.unwrap();<br \/>\n            socket.write_all(&amp;buf[..n]).await.unwrap();<br \/>\n        });<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ \u5ba2\u6237\u7aef<br \/>\nuse tokio::net::TcpStream;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let mut stream &#061; TcpStream::connect(&#034;127.0.0.1:8080&#034;).await.unwrap();<br \/>\n    stream.write_all(b&#034;hello&#034;).await.unwrap();<br \/>\n    let mut buf &#061; [0; 5];<br \/>\n    stream.read_exact(&amp;mut buf).await.unwrap();<br \/>\n    assert_eq!(b&#034;hello&#034;, &amp;buf);<br \/>\n}<\/p>\n<h4>\u5b9a\u65f6\u4e0e\u5ef6\u8fdf<\/h4>\n<p>\u4f7f\u7528 tokio::time \u5b9e\u73b0\u5ef6\u8fdf\u548c\u95f4\u9694\u4efb\u52a1&#xff1a;<\/p>\n<p>use tokio::time::{sleep, Duration};<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    sleep(Duration::from_secs(1)).await;<br \/>\n    println!(&#034;1 second later&#034;);<\/p>\n<p>    let mut interval &#061; tokio::time::interval(Duration::from_secs(2));<br \/>\n    for _ in 0..3 {<br \/>\n        interval.tick().await;<br \/>\n        println!(&#034;Tick every 2 seconds&#034;);<br \/>\n    }<br \/>\n}<\/p>\n<hr \/>\n<h4>\u5f02\u6b65\u6587\u4ef6 I\/O<\/h4>\n<p>\u8bfb\u5199\u6587\u4ef6\u5f02\u6b65\u64cd\u4f5c&#xff1a;<\/p>\n<p>use tokio::fs;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    fs::write(&#034;test.txt&#034;, b&#034;hello tokio&#034;).await.unwrap();<br \/>\n    let content &#061; fs::read(&#034;test.txt&#034;).await.unwrap();<br \/>\n    println!(&#034;{:?}&#034;, String::from_utf8(content).unwrap());<br \/>\n}<\/p>\n<h4>\u5e76\u53d1\u63a7\u5236<\/h4>\n<p>\u4f7f\u7528\u4fe1\u53f7\u91cf\u9650\u5236\u5e76\u53d1\u4efb\u52a1\u6570\u91cf&#xff1a;<\/p>\n<p>use tokio::sync::Semaphore;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let semaphore &#061; Semaphore::new(3);<br \/>\n    for i in 0..10 {<br \/>\n        let permit &#061; semaphore.acquire().await.unwrap();<br \/>\n        tokio::spawn(async move {<br \/>\n            println!(&#034;Task {} started&#034;, i);<br \/>\n            tokio::time::sleep(Duration::from_secs(1)).await;<br \/>\n            drop(permit); \/\/ \u91ca\u653e\u4fe1\u53f7\u91cf<br \/>\n        });<br \/>\n    }<br \/>\n    tokio::time::sleep(Duration::from_secs(5)).await;<br \/>\n}<\/p>\n<h4>\u5f02\u6b65\u9501\u4e0e\u5171\u4eab\u72b6\u6001<\/h4>\n<p>\u4f7f\u7528 Mutex \u4fdd\u62a4\u5171\u4eab\u6570\u636e&#xff1a;<\/p>\n<p>use tokio::sync::Mutex;<br \/>\nuse std::sync::Arc;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let counter &#061; Arc::new(Mutex::new(0));<br \/>\n    for _ in 0..10 {<br \/>\n        let counter &#061; Arc::clone(&amp;counter);<br \/>\n        tokio::spawn(async move {<br \/>\n            let mut num &#061; counter.lock().await;<br \/>\n            *num &#043;&#061; 1;<br \/>\n        });<br \/>\n    }<br \/>\n    tokio::time::sleep(Duration::from_secs(1)).await;<br \/>\n    println!(&#034;Result: {}&#034;, *counter.lock().await);<br \/>\n}<\/p>\n<h4>\u5f02\u6b65 HTTP \u8bf7\u6c42<\/h4>\n<p>\u4f7f\u7528 reqwest \u5e93&#xff08;\u57fa\u4e8e Tokio&#xff09;\u53d1\u9001 HTTP \u8bf7\u6c42&#xff1a;<\/p>\n<p>use reqwest;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let response &#061; reqwest::get(&#034;https:\/\/httpbin.org\/get&#034;)<br \/>\n        .await<br \/>\n        .unwrap()<br \/>\n        .text()<br \/>\n        .await<br \/>\n        .unwrap();<br \/>\n    println!(&#034;{}&#034;, response);<br \/>\n}<\/p>\n<h4>WebSocket \u901a\u4fe1<\/h4>\n<p>\u4f7f\u7528 tokio-tungstenite \u5b9e\u73b0 WebSocket \u5ba2\u6237\u7aef&#xff1a;<\/p>\n<p>use tokio_tungstenite::connect_async;<br \/>\nuse tungstenite::protocol::Message;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let url &#061; &#034;ws:\/\/echo.websocket.org&#034;;<br \/>\n    let (mut socket, _) &#061; connect_async(url).await.unwrap();<br \/>\n    socket.send(Message::Text(&#034;Hello&#034;.into())).await.unwrap();<br \/>\n    let msg &#061; socket.next().await.unwrap().unwrap();<br \/>\n    println!(&#034;Received: {}&#034;, msg);<br \/>\n}<\/p>\n<h4>\u81ea\u5b9a\u4e49\u5f02\u6b65\u4efb\u52a1\u53d6\u6d88<\/h4>\n<p>\u901a\u8fc7 tokio::select! \u5b9e\u73b0\u4efb\u52a1\u53d6\u6d88&#xff1a;<\/p>\n<p>use tokio::sync::oneshot;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let (tx, rx) &#061; oneshot::channel();<br \/>\n    tokio::spawn(async move {<br \/>\n        tokio::select! {<br \/>\n            _ &#061; async { tokio::time::sleep(Duration::from_secs(5)).await } &#061;&gt; {<br \/>\n                println!(&#034;Task completed&#034;);<br \/>\n            }<br \/>\n            _ &#061; rx &#061;&gt; {<br \/>\n                println!(&#034;Task cancelled&#034;);<br \/>\n            }<br \/>\n        }<br \/>\n    });<br \/>\n    tx.send(()).unwrap();<br \/>\n    tokio::time::sleep(Duration::from_secs(1)).await;<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u5f02\u6b65\u65e5\u5fd7\u8bb0\u5f55<\/h4>\n<p>\u4f7f\u7528 tracing \u5e93\u4e0e Tokio \u96c6\u6210&#xff1a;<\/p>\n<p>use tracing::{info, Level};<br \/>\nuse tracing_subscriber::fmt;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    fmt().with_max_level(Level::INFO).init();<br \/>\n    info!(&#034;This is an async log message&#034;);<br \/>\n}<\/p>\n<p>\u4ee5\u4e0a\u6848\u4f8b\u8986\u76d6\u4e86 Tokio \u7684\u5e38\u89c1\u4f7f\u7528\u573a\u666f\u3002\u5982\u9700\u66f4\u590d\u6742\u7684\u793a\u4f8b<\/p>\n<p>&#xff08;\u5982\u81ea\u5b9a\u4e49\u8fd0\u884c\u65f6\u3001UDP \u901a\u4fe1\u3001gRPC \u96c6\u6210\u7b49&#xff09;&#xff0c;\u53ef\u53c2\u8003 Tokio \u5b98\u65b9\u6587\u6863\u6216\u7b2c\u4e09\u65b9\u5e93\u7684\u793a\u4f8b\u4ee3\u7801\u3002<\/p>\n<h3>\u5b57\u8282\u8df3\u52a8\u5f00\u6e90\u9879\u76ee Monio<\/h3>\n<p>\u4ee5\u4e0b\u662f\u5173\u4e8e\u5b57\u8282\u8df3\u52a8\u5f00\u6e90\u9879\u76ee Monio \u7684\u793a\u4f8b\u7684\u6574\u7406\u548c\u5206\u6790\u3002Monio \u662f\u4e00\u4e2a\u57fa\u4e8e Rust \u7684\u5f02\u6b65\u7f16\u7a0b\u5e93&#xff0c;\u4e13\u6ce8\u4e8e\u63d0\u4f9b\u9ad8\u6027\u80fd\u7684 I\/O \u64cd\u4f5c\u548c\u5e76\u53d1\u5904\u7406\u80fd\u529b\u3002<\/p>\n<h4 style=\"background-color:transparent\">Monio \u7684\u6838\u5fc3\u529f\u80fd<\/h4>\n<p>Monio \u63d0\u4f9b\u4e86\u5f02\u6b65 I\/O\u3001\u4efb\u52a1\u8c03\u5ea6\u3001\u534f\u7a0b\u7ba1\u7406\u7b49\u6838\u5fc3\u529f\u80fd&#xff0c;\u9002\u7528\u4e8e\u9ad8\u5e76\u53d1\u573a\u666f\u3002\u5176\u8bbe\u8ba1\u7406\u5ff5\u662f\u901a\u8fc7 Rust \u7684\u6240\u6709\u6743\u6a21\u578b\u548c\u96f6\u6210\u672c\u62bd\u8c61&#xff0c;\u5b9e\u73b0\u9ad8\u6548\u4e14\u5b89\u5168\u7684\u5f02\u6b65\u7f16\u7a0b\u3002<\/p>\n<h4>\u793a\u4f8b\u5206\u7c7b<\/h4>\n<li>\n<p>\u57fa\u7840\u5f02\u6b65\u64cd\u4f5c \u5305\u62ec\u6587\u4ef6\u8bfb\u5199\u3001\u7f51\u7edc\u8bf7\u6c42\u7b49\u57fa\u7840\u64cd\u4f5c\u7684\u5f02\u6b65\u5b9e\u73b0\u3002\u793a\u4f8b\u4ee3\u7801\u5c55\u793a\u4e86\u5982\u4f55\u901a\u8fc7 Monio \u7684 API \u5b8c\u6210\u975e\u963b\u585e I\/O\u3002<\/p>\n<p> use monio::fs::File;<br \/>\nuse monio::io::AsyncReadExt;<\/p>\n<p>async fn read_file() {<br \/>\n    let mut file &#061; File::open(&#034;example.txt&#034;).await.unwrap();<br \/>\n    let mut contents &#061; vec![];<br \/>\n    file.read_to_end(&amp;mut contents).await.unwrap();<br \/>\n    println!(&#034;File contents: {:?}&#034;, contents);<br \/>\n}\n <\/li>\n<li>\n<p>\u4efb\u52a1\u8c03\u5ea6 Monio \u7684\u4efb\u52a1\u8c03\u5ea6\u5668\u5141\u8bb8\u7528\u6237\u9ad8\u6548\u7ba1\u7406\u5f02\u6b65\u4efb\u52a1\u3002\u793a\u4f8b\u5305\u62ec\u4efb\u52a1\u7684\u521b\u5efa\u3001\u53d6\u6d88\u548c\u4f18\u5148\u7ea7\u8c03\u5ea6\u3002<\/p>\n<p> use monio::task::spawn;<\/p>\n<p>async fn run_task() {<br \/>\n    let handle &#061; spawn(async {<br \/>\n        println!(&#034;Task executed&#034;);<br \/>\n    });<br \/>\n    handle.await.unwrap();<br \/>\n}\n <\/li>\n<li>\n<p>\u534f\u7a0b\u7ba1\u7406 \u901a\u8fc7\u534f\u7a0b\u5b9e\u73b0\u8f7b\u91cf\u7ea7\u5e76\u53d1\u3002\u793a\u4f8b\u5c55\u793a\u4e86\u534f\u7a0b\u7684\u521b\u5efa\u3001\u6682\u505c\u548c\u6062\u590d\u3002<\/p>\n<p> use monio::coroutine;<\/p>\n<p>async fn coroutine_example() {<br \/>\n    let co &#061; coroutine::spawn(|| {<br \/>\n        println!(&#034;Coroutine running&#034;);<br \/>\n    });<br \/>\n    co.join().await;<br \/>\n}\n <\/li>\n<li>\n<p>\u7f51\u7edc\u7f16\u7a0b \u5305\u62ec TCP\/UDP \u901a\u4fe1\u3001HTTP \u670d\u52a1\u5668\u7b49\u7f51\u7edc\u76f8\u5173\u793a\u4f8b\u3002<\/p>\n<p> use monio::net::TcpListener;<\/p>\n<p>async fn tcp_server() {<br \/>\n    let listener &#061; TcpListener::bind(&#034;127.0.0.1:8080&#034;).await.unwrap();<br \/>\n    while let Ok((stream, _)) &#061; listener.accept().await {<br \/>\n        println!(&#034;New connection&#034;);<br \/>\n    }<br \/>\n}\n <\/li>\n<li>\n<p>\u6027\u80fd\u4f18\u5316 \u793a\u4f8b\u5c55\u793a\u4e86\u5982\u4f55\u901a\u8fc7 Monio \u7684\u96f6\u6210\u672c\u62bd\u8c61\u548c\u5185\u5b58\u6c60\u6280\u672f\u4f18\u5316\u6027\u80fd\u3002<\/p>\n<p> use monio::mem::Pool;<\/p>\n<p>async fn memory_pool() {<br \/>\n    let pool &#061; Pool::new();<br \/>\n    let buffer &#061; pool.alloc(1024).await;<br \/>\n    println!(&#034;Buffer allocated&#034;);<br \/>\n}\n <\/li>\n<li>\n<p>\u9519\u8bef\u5904\u7406 \u793a\u4f8b\u6db5\u76d6\u4e86\u5f02\u6b65\u7f16\u7a0b\u4e2d\u7684\u9519\u8bef\u5904\u7406\u6a21\u5f0f&#xff0c;\u5305\u62ec\u81ea\u5b9a\u4e49\u9519\u8bef\u548c\u94fe\u5f0f\u5904\u7406\u3002<\/p>\n<p> use monio::error::Error;<\/p>\n<p>async fn error_handling() -&gt; Result&lt;(), Error&gt; {<br \/>\n    let result &#061; some_async_operation().await?;<br \/>\n    Ok(())<br \/>\n}\n <\/li>\n<li>\n<p>\u96c6\u6210\u6d4b\u8bd5 \u793a\u4f8b\u63d0\u4f9b\u4e86\u5982\u4f55\u7f16\u5199\u9488\u5bf9 Monio \u7ec4\u4ef6\u7684\u96c6\u6210\u6d4b\u8bd5\u3002<\/p>\n<p> #[cfg(test)]<br \/>\nmod tests {<br \/>\n    use super::*;<br \/>\n    use monio::runtime::Runtime;<\/p>\n<p>    #[test]<br \/>\n    fn test_async_op() {<br \/>\n        Runtime::new().block_on(async {<br \/>\n            assert_eq!(some_async_operation().await, 42);<br \/>\n        });<br \/>\n    }<br \/>\n}\n <\/li>\n<h4 style=\"background-color:transparent\">\u83b7\u53d6\u5b8c\u6574\u793a\u4f8b<\/h4>\n<p>\u5b8c\u6574 \u793a\u4f8b\u53ef\u4ee5\u4ece Monio \u7684\u5b98\u65b9 GitHub \u4ed3\u5e93\u83b7\u53d6&#xff1a;<\/p>\n<p>\u6bcf\u4e2a\u793a\u4f8b\u5747\u9644\u6709\u8be6\u7ec6\u6ce8\u91ca\u548c\u7528\u6cd5\u8bf4\u660e&#xff0c;\u9002\u5408\u4ece\u5165\u95e8\u5230\u9ad8\u7ea7\u7684\u4e0d\u540c\u9700\u6c42\u3002<\/p>\n<h3 style=\"background-color:transparent\">\u57fa\u4e8e Golang \u548c CloudWeGo \u5b9e\u4f8b<\/h3>\n<p>\u73af\u5883\u51c6\u5907 \u786e\u4fdd\u5df2\u5b89\u88c5 Golang&#xff08;1.18 \u6216\u66f4\u9ad8\u7248\u672c&#xff09;\u548c CloudWeGo \u76f8\u5173\u5de5\u5177\u94fe&#xff08;\u5982 Kitex \u548c Hertz&#xff09;\u3002\u8fd0\u884c\u4ee5\u4e0b\u547d\u4ee4\u5b89\u88c5\u4f9d\u8d56&#xff1a;<\/p>\n<p>go install github.com\/cloudwego\/kitex\/tool\/cmd\/kitex&#064;latest<br \/>\ngo install github.com\/cloudwego\/hertz\/cmd\/hz&#064;latest<\/p>\n<p>\u9879\u76ee\u521d\u59cb\u5316 \u521b\u5efa\u9879\u76ee\u76ee\u5f55\u5e76\u521d\u59cb\u5316\u6a21\u5757&#xff1a;<\/p>\n<p>mkdir cloudwego-100-examples<br \/>\ncd cloudwego-100-examples<br \/>\ngo mod init github.com\/yourname\/cloudwego-100-examples<\/p>\n<p>\u670d\u52a1\u6846\u67b6\u9009\u62e9 CloudWeGo \u63d0\u4f9b Kitex&#xff08;RPC \u6846\u67b6&#xff09;\u548c Hertz&#xff08;HTTP \u6846\u67b6&#xff09;\u3002\u6839\u636e\u573a\u666f\u9009\u62e9&#xff1a;<\/p>\n<ul>\n<li>\u5fae\u670d\u52a1\u5185\u90e8\u901a\u4fe1&#xff1a;Kitex<\/li>\n<li>API \u7f51\u5173\u6216 Web \u670d\u52a1&#xff1a;Hertz<\/li>\n<\/ul>\n<p>\u793a\u4f8b\u4ee3\u7801\u7ed3\u6784 \u91c7\u7528\u6a21\u5757\u5316\u7ec4\u7ec7&#xff0c;\u6bcf\u4e2a\u5b9e\u4f8b\u72ec\u7acb\u76ee\u5f55\u3002\u4f8b\u5982&#xff1a;<\/p>\n<p>\/examples<br \/>\n  \/example1-kitex-basic<br \/>\n  \/example2-hertz-basic<br \/>\n  \/example3-middleware<br \/>\n  &#8230;<\/p>\n<h4 style=\"background-color:transparent\">\u5b9e\u4f8b\u5206\u7c7b\u4e0e\u5b9e\u73b0<\/h4>\n<p>\u57fa\u7840 RPC \u670d\u52a1&#xff08;Kitex&#xff09; \u5b9a\u4e49 IDL \u6587\u4ef6&#xff08;\u5982 echo.thrift&#xff09;&#xff1a;<\/p>\n<p>service Echo {<br \/>\n    string echo(1: string req);<br \/>\n}<\/p>\n<p>\u751f\u6210\u4ee3\u7801&#xff1a;<\/p>\n<p>kitex -module github.com\/yourname\/cloudwego-100-examples -service Echo echo.thrift<\/p>\n<p>\u5b9e\u73b0\u670d\u52a1\u903b\u8f91&#xff1a;<\/p>\n<p>type EchoServiceImpl struct{}<\/p>\n<p>func (e *EchoServiceImpl) Echo(ctx context.Context, req string) (string, error) {<br \/>\n    return &#034;Response: &#034; &#043; req, nil<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">HTTP \u670d\u52a1&#xff08;Hertz&#xff09;<\/h4>\n<p>\u521d\u59cb\u5316 Hertz \u9879\u76ee&#xff1a;<\/p>\n<p>hz new -module github.com\/yourname\/cloudwego-100-examples<\/p>\n<p>\u6dfb\u52a0\u8def\u7531\u548c\u5904\u7406\u51fd\u6570&#xff1a;<\/p>\n<p>h.GET(&#034;\/ping&#034;, func(c context.Context, ctx *app.RequestContext) {<br \/>\n    ctx.JSON(200, map[string]string{&#034;message&#034;: &#034;pong&#034;})<br \/>\n})<\/p>\n<h4>\u9ad8\u7ea7\u529f\u80fd\u5b9e\u4f8b<\/h4>\n<ul>\n<li>\u8d1f\u8f7d\u5747\u8861: \u5728 Kitex \u5ba2\u6237\u7aef\u914d\u7f6e&#xff1a;<\/li>\n<\/ul>\n<p>cli :&#061; echoservice.MustNewClient(<br \/>\n    &#034;echo&#034;,<br \/>\n    client.WithLoadBalancer(loadbalance.NewWeightedBalancer()),<br \/>\n)<\/p>\n<ul>\n<li>\u670d\u52a1\u6ce8\u518c\u53d1\u73b0: \u96c6\u6210 Nacos \u6216 Etcd&#xff1a;<\/li>\n<\/ul>\n<p>registry, err :&#061; consul.NewConsulRegistry(&#034;127.0.0.1:8500&#034;)<\/p>\n<ul>\n<li>\u94fe\u8def\u8ffd\u8e2a: \u4f7f\u7528 OpenTelemetry&#xff1a;<\/li>\n<\/ul>\n<p>provider :&#061; otel.GetTracerProvider()<br \/>\ntracer :&#061; provider.Tracer(&#034;example&#034;)<\/p>\n<h4>\u6027\u80fd\u4f18\u5316<\/h4>\n<ul>\n<li>\u8fde\u63a5\u590d\u7528: Kitex \u9ed8\u8ba4\u542f\u7528\u8fde\u63a5\u6c60<\/li>\n<li>\u5e8f\u5217\u5316: \u4f7f\u7528 Sonic \u66ff\u4ee3 JSON&#xff1a;<\/li>\n<\/ul>\n<p>h.Use(hertzSonic.WithConfig(sonic.Config{UseNumber: true}))<\/p>\n<h4>\u90e8\u7f72\u65b9\u6848<\/h4>\n<ul>\n<li>\u5bb9\u5668\u5316: \u7f16\u5199 Dockerfile \u591a\u9636\u6bb5\u6784\u5efa<\/li>\n<li>K8S \u90e8\u7f72: \u914d\u7f6e Helm Chart \u6216 Kustomize<\/li>\n<li>Serverless: \u9002\u914d AWS Lambda \u6216 Knative<\/li>\n<\/ul>\n<h4 style=\"background-color:transparent\">\u76d1\u63a7\u4e0e\u8fd0\u7ef4<\/h4>\n<ul>\n<li>\u6307\u6807\u6536\u96c6: \u96c6\u6210 Prometheus&#xff1a;<\/li>\n<\/ul>\n<p>registry :&#061; prometheus.NewRegistry()<br \/>\nkitexRegistry :&#061; metrics.NewKitexRegistry(registry)<\/p>\n<ul>\n<li>\u65e5\u5fd7\u7ba1\u7406: \u4f7f\u7528 Zap \u6216 Logrus<\/li>\n<\/ul>\n<p>\u5b8c\u6574\u4ee3\u7801\u9700\u7ed3\u5408\u5177\u4f53\u573a\u666f\u8c03\u6574&#xff0c;\u5efa\u8bae\u53c2\u8003 CloudWeGo \u5b98\u65b9\u6587\u6863\u548c\u793a\u4f8b\u4ed3\u5e93\u9010\u6b65\u6269\u5c55\u3002\u6bcf\u4e2a\u5b9e\u4f8b\u5e94\u5305\u542b\u6d4b\u8bd5\u7528\u4f8b\u548c Benchmark&#xff0c;\u786e\u4fdd\u8d28\u91cf\u4e0e\u6027\u80fd\u3002<\/p>\n<p>\u4ee5\u4e0b\u662f\u57fa\u4e8e Rust Kitex&#xff08;RPC \u6846\u67b6&#xff09;\u7684 \u5b9e\u7528\u793a\u4f8b&#xff0c;\u6db5\u76d6\u57fa\u7840\u529f\u80fd\u5230\u9ad8\u7ea7\u7528\u6cd5&#xff1a;<\/p>\n<h3 style=\"background-color:transparent\">\u57fa\u7840 RPC \u670d\u52a1\u5b9a\u4e49\u4e0e\u8c03\u7528<\/h3>\n<p>\/\/ \u5b9a\u4e49 Thrift \u670d\u52a1<br \/>\nservice HelloService {<br \/>\n    string say_hello(1: string name)<br \/>\n}  <\/p>\n<p>\/\/ \u751f\u6210\u4ee3\u7801\u540e\u5b9e\u73b0\u670d\u52a1\u7aef<br \/>\nstruct HelloServiceImpl;<br \/>\nimpl HelloService for HelloServiceImpl {<br \/>\n    fn say_hello(&amp;self, name: String) -&gt; Result&lt;String&gt; {<br \/>\n        Ok(format!(&#034;Hello, {}!&#034;, name))<br \/>\n    }<br \/>\n}  <\/p>\n<p>\/\/ \u5ba2\u6237\u7aef\u8c03\u7528<br \/>\nlet transport &#061; TTcpTransport::new();<br \/>\nlet client &#061; HelloServiceClient::new(transport);<br \/>\nlet response &#061; client.say_hello(&#034;Kitex&#034;.to_string())?;  <\/p>\n<h4>\u5f02\u6b65\u670d\u52a1\u7aef\u5b9e\u73b0<\/h4>\n<p>#[async_trait]<br \/>\nimpl HelloService for HelloServiceImpl {<br \/>\n    async fn say_hello(&amp;self, name: String) -&gt; Result&lt;String&gt; {<br \/>\n        tokio::time::sleep(Duration::from_secs(1)).await;<br \/>\n        Ok(format!(&#034;Async Hello, {}!&#034;, name))<br \/>\n    }<br \/>\n}  <\/p>\n<h4>\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6&#xff08;Middleware&#xff09;<\/h4>\n<p>\/\/ \u8bb0\u5f55\u8bf7\u6c42\u8017\u65f6\u7684\u4e2d\u95f4\u4ef6<br \/>\nfn logging_middleware&lt;T&gt;(next: T) -&gt; impl Service<br \/>\nwhere T: Service&lt;Request&gt; {<br \/>\n    service_fn(move |req| {<br \/>\n        let start &#061; Instant::now();<br \/>\n        next.call(req).map(move |res| {<br \/>\n            println!(&#034;Request took {:?}&#034;, start.elapsed());<br \/>\n            res<br \/>\n        })<br \/>\n    })<br \/>\n}  <\/p>\n<p>\/\/ \u6ce8\u518c\u5230\u670d\u52a1\u5668<br \/>\nserver.with_middleware(logging_middleware);  <\/p>\n<h4>\u8d1f\u8f7d\u5747\u8861\u5ba2\u6237\u7aef<\/h4>\n<p>let resolver &#061; DnsResolver::new();<br \/>\nlet balancer &#061; LoadBalancer::new(resolver);<br \/>\nlet client &#061; HelloServiceClient::with_load_balancer(balancer);  <\/p>\n<h4>TLS \u52a0\u5bc6\u901a\u4fe1<\/h4>\n<p>\/\/ \u670d\u52a1\u7aef\u914d\u7f6e<br \/>\nlet tls_config &#061; TlsServerConfig::from_pem(&#034;server.pem&#034;, &#034;server.key&#034;);<br \/>\nserver.with_tls(tls_config);  <\/p>\n<p>\/\/ \u5ba2\u6237\u7aef\u914d\u7f6e<br \/>\nlet tls_config &#061; TlsClientConfig::new().ca_cert(&#034;ca.pem&#034;);<br \/>\nlet transport &#061; TTcpTransport::with_tls(&#034;localhost:3000&#034;, tls_config);  <\/p>\n<h4>\u670d\u52a1\u6ce8\u518c\u4e0e\u53d1\u73b0&#xff08;ETCD&#xff09;<\/h4>\n<p>let registry &#061; EtcdRegistry::new(&#034;http:\/\/etcd:2379&#034;);<br \/>\nserver.with_registry(registry);  <\/p>\n<p>\/\/ \u5ba2\u6237\u7aef\u53d1\u73b0<br \/>\nlet discovery &#061; EtcdDiscovery::new(&#034;http:\/\/etcd:2379&#034;, &#034;hello_service&#034;);<br \/>\nlet client &#061; HelloServiceClient::with_discovery(discovery);  <\/p>\n<h4>\u591a\u8def\u590d\u7528&#xff08;Multiplexing&#xff09;<\/h4>\n<p>\/\/ \u670d\u52a1\u7aef\u652f\u6301\u591a\u670d\u52a1<br \/>\nserver<br \/>\n    .add_service(HelloServiceServer::new(HelloServiceImpl))<br \/>\n    .add_service(AnotherServiceServer::new(AnotherServiceImpl));  <\/p>\n<p>\/\/ \u5ba2\u6237\u7aef\u591a\u8def\u590d\u7528<br \/>\nlet multiplexed_client &#061; MultiplexedClient::new(transport);<br \/>\nlet hello_client &#061; multiplexed_client.get_client::&lt;HelloServiceClient&gt;();  <\/p>\n<h4>\u6027\u80fd\u7edf\u8ba1&#xff08;Metrics&#xff09;<\/h4>\n<p>\/\/ \u96c6\u6210 Prometheus<br \/>\nserver.with_metrics(PrometheusMetrics::new());  <\/p>\n<p>\/\/ \u81ea\u5b9a\u4e49\u7edf\u8ba1<br \/>\nserver.with_metrics_callback(|req, latency| {<br \/>\n    MY_COUNTER.inc();<br \/>\n});  <\/p>\n<h4>\u81ea\u5b9a\u4e49\u534f\u8bae\u7f16\u7801<\/h4>\n<p>\/\/ \u4f7f\u7528 JSON \u7f16\u7801\u66ff\u4ee3 Thrift<br \/>\nserver.with_codec(JsonCodec::new());  <\/p>\n<p>\/\/ \u5ba2\u6237\u7aef\u5339\u914d<br \/>\nlet transport &#061; TTcpTransport::with_codec(&#034;localhost:3000&#034;, JsonCodec::new());  <\/p>\n<h4 style=\"background-color:transparent\">\u6d41\u5f0f\u4f20\u8f93&#xff08;Streaming&#xff09;<\/h4>\n<p>\/\/ \u5b9a\u4e49\u6d41\u5f0f\u670d\u52a1<br \/>\nservice StreamService {<br \/>\n    stream&lt;string&gt; word_stream(1: i32 count)<br \/>\n}  <\/p>\n<p>\/\/ \u5b9e\u73b0\u6d41\u5f0f\u54cd\u5e94<br \/>\nimpl StreamService for StreamServiceImpl {<br \/>\n    fn word_stream(&amp;self, count: i32) -&gt; Result&lt;Stream&lt;String&gt;&gt; {<br \/>\n        let stream &#061; stream::iter((0..count).map(|i| Ok(format!(&#034;Word {}&#034;, i))));<br \/>\n        Ok(Box::pin(stream))<br \/>\n    }<br \/>\n}  <\/p>\n<p>\u4ee5\u4e0a\u793a\u4f8b\u8986\u76d6\u4e86 Kitex \u7684\u6838\u5fc3\u529f\u80fd&#xff0c;\u5305\u62ec\u540c\u6b65\/\u5f02\u6b65\u5904\u7406\u3001\u4e2d\u95f4\u4ef6\u3001\u5b89\u5168\u901a\u4fe1\u3001\u670d\u52a1\u6cbb\u7406\u7b49\u573a\u666f\u3002\u5b9e\u9645\u4f7f\u7528\u65f6\u9700\u6839\u636e Kitex \u6700\u65b0\u7248\u672c\u8c03\u6574 API \u7ec6\u8282\u3002<\/p>\n<h3>Rust \u7684 Hertz&#xff08;HTTP \u6846\u67b6&#xff09;<\/h3>\n<p>\u4ee5\u4e0b\u662f\u57fa\u4e8e Rust \u7684 Hertz&#xff08;HTTP \u6846\u67b6&#xff09;\u7684\u5b9e\u7528\u793a\u4f8b&#xff0c;\u6db5\u76d6\u57fa\u7840\u529f\u80fd\u3001\u4e2d\u95f4\u4ef6\u3001\u8def\u7531\u3001\u9519\u8bef\u5904\u7406\u7b49\u5e38\u89c1\u573a\u666f\u3002\u793a\u4f8b\u57fa\u4e8e hertz \u548c tokio \u751f\u6001&#xff0c;\u4ee3\u7801\u53ef\u76f4\u63a5\u8fd0\u884c&#xff08;\u9700\u6dfb\u52a0\u4f9d\u8d56&#xff09;\u3002<\/p>\n<h4 style=\"background-color:transparent\">\u57fa\u7840 HTTP \u670d\u52a1\u5668<\/h4>\n<p>use hertz::{router, Server};<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let mut router &#061; router::Router::new();<br \/>\n    router.get(&#034;\/&#034;, |_| async { &#034;Hello, Hertz!&#034; });<\/p>\n<p>    Server::new()<br \/>\n        .bind(&#034;127.0.0.1:3000&#034;)<br \/>\n        .serve(router)<br \/>\n        .await<br \/>\n        .unwrap();<br \/>\n}<\/p>\n<h4>\u8def\u7531\u53c2\u6570\u5904\u7406<\/h4>\n<p>router.get(&#034;\/user\/:id&#034;, |req| async move {<br \/>\n    let id &#061; req.param(&#034;id&#034;).unwrap();<br \/>\n    format!(&#034;User ID: {}&#034;, id)<br \/>\n});<\/p>\n<h4>JSON \u8bf7\u6c42\u4e0e\u54cd\u5e94<\/h4>\n<p>use serde::{Deserialize, Serialize};<\/p>\n<p>#[derive(Serialize, Deserialize)]<br \/>\nstruct User {<br \/>\n    name: String,<br \/>\n    age: u32,<br \/>\n}<\/p>\n<p>router.post(&#034;\/json&#034;, |mut req| async move {<br \/>\n    let user: User &#061; req.json().await.unwrap();<br \/>\n    hertz::Response::json(&amp;user)<br \/>\n});<\/p>\n<h4>\u9759\u6001\u6587\u4ef6\u670d\u52a1<\/h4>\n<p>use hertz::fs::Static;<\/p>\n<p>router.get(&#034;\/static\/*path&#034;, Static::new(&#034;public\/&#034;));<\/p>\n<h4>\u4e2d\u95f4\u4ef6\u793a\u4f8b&#xff08;\u65e5\u5fd7\u8bb0\u5f55&#xff09;<\/h4>\n<p>use hertz::middleware::{Logger, Next};<br \/>\nuse std::time::Instant;<\/p>\n<p>async fn log_middleware(req: hertz::Request, next: Next) -&gt; hertz::Result {<br \/>\n    let start &#061; Instant::now();<br \/>\n    let path &#061; req.uri().path();<br \/>\n    let res &#061; next.run(req).await?;<br \/>\n    println!(&#034;{} {}ms&#034;, path, start.elapsed().as_millis());<br \/>\n    Ok(res)<br \/>\n}<\/p>\n<p>Server::new()<br \/>\n    .bind(&#034;127.0.0.1:3000&#034;)<br \/>\n    .middleware(log_middleware)<br \/>\n    .serve(router);<\/p>\n<h4>\u81ea\u5b9a\u4e49\u9519\u8bef\u5904\u7406<\/h4>\n<p>use hertz::{Error, Response};<\/p>\n<p>router.get(&#034;\/error&#034;, |_| async {<br \/>\n    Err(Error::new(&#034;Custom error&#034;).status(400))<br \/>\n});<\/p>\n<p>Server::new()<br \/>\n    .error_handler(|err| {<br \/>\n        Response::new()<br \/>\n            .status(err.status())<br \/>\n            .body(err.to_string())<br \/>\n    })<br \/>\n    .serve(router);<\/p>\n<h4>WebSocket \u652f\u6301<\/h4>\n<p>use hertz::ws::{Message, WebSocket};<\/p>\n<p>router.get(&#034;\/ws&#034;, |req| async {<br \/>\n    WebSocket::new(req, |mut socket| async move {<br \/>\n        while let Some(msg) &#061; socket.recv().await {<br \/>\n            socket.send(msg?).await?;<br \/>\n        }<br \/>\n        Ok(())<br \/>\n    })<br \/>\n});<\/p>\n<h4>\u6570\u636e\u5e93\u96c6\u6210&#xff08;SQLx&#xff09;<\/h4>\n<p>use sqlx::postgres::PgPoolOptions;<\/p>\n<p>#[derive(sqlx::FromRow)]<br \/>\nstruct Post {<br \/>\n    id: i32,<br \/>\n    title: String,<br \/>\n}<\/p>\n<p>router.get(&#034;\/posts&#034;, |req| async {<br \/>\n    let pool &#061; req.extensions().get::&lt;sqlx::PgPool&gt;().unwrap();<br \/>\n    let posts &#061; sqlx::query_as::&lt;_, Post&gt;(&#034;SELECT * FROM posts&#034;)<br \/>\n        .fetch_all(pool)<br \/>\n        .await?;<br \/>\n    hertz::Response::json(&amp;posts)<br \/>\n});<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let pool &#061; PgPoolOptions::new()<br \/>\n        .connect(&#034;postgres:\/\/user:pass&#064;localhost\/db&#034;)<br \/>\n        .await<br \/>\n        .unwrap();<\/p>\n<p>    let mut router &#061; router::Router::new();<br \/>\n    router.with(pool).get(&#034;\/posts&#034;, \/* &#8230; *\/);<br \/>\n}<\/p>\n<h4>\u9650\u6d41\u4e2d\u95f4\u4ef6<\/h4>\n<p>use std::sync::Arc;<br \/>\nuse governor::{DefaultKeyedRateLimiter, Quota, RateLimiter};<\/p>\n<p>async fn rate_limit(<br \/>\n    req: hertz::Request,<br \/>\n    next: Next,<br \/>\n    limiter: Arc&lt;RateLimiter&lt;String&gt;&gt;,<br \/>\n) -&gt; hertz::Result {<br \/>\n    let key &#061; req.ip().to_string();<br \/>\n    limiter.check_key(&amp;key)?;<br \/>\n    next.run(req).await<br \/>\n}<\/p>\n<p>let limiter &#061; Arc::new(DefaultKeyedRateLimiter::per_second(Quota::per_second(10)));<br \/>\nrouter.middleware(move |req, next| rate_limit(req, next, limiter.clone()));<\/p>\n<h4 style=\"background-color:transparent\">JWT \u8ba4\u8bc1<\/h4>\n<p>use jsonwebtoken::{decode, Validation, Algorithm};<\/p>\n<p>router.post(&#034;\/login&#034;, |mut req| async {<br \/>\n    let creds: LoginRequest &#061; req.json().await?;<br \/>\n    let token &#061; generate_jwt(creds)?;<br \/>\n    Response::json(&amp;token)<br \/>\n});<\/p>\n<p>router.get(&#034;\/protected&#034;, |req| async {<br \/>\n    let token &#061; req.header(&#034;Authorization&#034;)?.strip_prefix(&#034;Bearer &#034;)?;<br \/>\n    decode::&lt;Claims&gt;(token, &amp;SECRET, &amp;Validation::new(Algorithm::HS256))?;<br \/>\n    &#034;Protected content&#034;<br \/>\n});<\/p>\n<h3 style=\"background-color:transparent\">\u57fa\u4e8e Go \u8bed\u8a00\u7684 Volo \u5b9e\u4f8b<\/h3>\n<p>\u4ee5\u4e0b\u662f\u57fa\u4e8e Go \u8bed\u8a00\u7684 Volo \u5b9e\u4f8b&#xff0c;\u6db5\u76d6\u7f51\u7edc\u7f16\u7a0b\u3001\u5e76\u53d1\u5904\u7406\u3001\u5fae\u670d\u52a1\u7b49\u9886\u57df\u3002\u7531\u4e8e\u7bc7\u5e45\u9650\u5236&#xff0c;\u4ee5\u4e0b\u4e3a\u90e8\u5206\u793a\u4f8b\u7684\u4ee3\u7801\u7247\u6bb5\u548c\u8bf4\u660e&#xff0c;\u5b8c\u6574\u5185\u5bb9\u53ef\u901a\u8fc7\u6269\u5c55\u5b9e\u73b0\u3002<\/p>\n<h4 style=\"background-color:transparent\">\u7f51\u7edc\u7f16\u7a0b\u793a\u4f8b<\/h4>\n<p>\/\/ \u793a\u4f8b1: HTTP \u670d\u52a1\u5668<br \/>\npackage main<br \/>\nimport (<br \/>\n    &#034;net\/http&#034;<br \/>\n    &#034;fmt&#034;<br \/>\n)<br \/>\nfunc handler(w http.ResponseWriter, r *http.Request) {<br \/>\n    fmt.Fprintf(w, &#034;Hello Volo!&#034;)<br \/>\n}<br \/>\nfunc main() {<br \/>\n    http.HandleFunc(&#034;\/&#034;, handler)<br \/>\n    http.ListenAndServe(&#034;:8080&#034;, nil)<br \/>\n}<\/p>\n<p>\/\/ \u793a\u4f8b2: TCP \u5ba2\u6237\u7aef<br \/>\npackage main<br \/>\nimport (<br \/>\n    &#034;net&#034;<br \/>\n    &#034;bufio&#034;<br \/>\n)<br \/>\nfunc main() {<br \/>\n    conn, _ :&#061; net.Dial(&#034;tcp&#034;, &#034;golang.org:80&#034;)<br \/>\n    fmt.Fprintf(conn, &#034;GET \/ HTTP\/1.0\\\\r\\\\n\\\\r\\\\n&#034;)<br \/>\n    status, _ :&#061; bufio.NewReader(conn).ReadString(&#039;\\\\n&#039;)<br \/>\n    fmt.Println(status)<br \/>\n}<\/p>\n<h4>\u5e76\u53d1\u5904\u7406\u793a\u4f8b<\/h4>\n<p>\/\/ \u793a\u4f8b3: Goroutine \u57fa\u7840<br \/>\npackage main<br \/>\nimport (<br \/>\n    &#034;fmt&#034;<br \/>\n    &#034;time&#034;<br \/>\n)<br \/>\nfunc worker(id int) {<br \/>\n    fmt.Printf(&#034;Worker %d started\\\\n&#034;, id)<br \/>\n    time.Sleep(time.Second)<br \/>\n    fmt.Printf(&#034;Worker %d done\\\\n&#034;, id)<br \/>\n}<br \/>\nfunc main() {<br \/>\n    for i :&#061; 1; i &lt;&#061; 5; i&#043;&#043; {<br \/>\n        go worker(i)<br \/>\n    }<br \/>\n    time.Sleep(time.Second * 2)<br \/>\n}<\/p>\n<p>\/\/ \u793a\u4f8b4: \u901a\u9053\u540c\u6b65<br \/>\npackage main<br \/>\nimport &#034;fmt&#034;<br \/>\nfunc main() {<br \/>\n    jobs :&#061; make(chan int, 5)<br \/>\n    go func() {<br \/>\n        for j :&#061; range jobs {<br \/>\n            fmt.Println(&#034;Received job&#034;, j)<br \/>\n        }<br \/>\n    }()<br \/>\n    for i :&#061; 1; i &lt;&#061; 3; i&#043;&#043; {<br \/>\n        jobs &lt;- i<br \/>\n    }<br \/>\n    close(jobs)<br \/>\n}<\/p>\n<h4>\u5fae\u670d\u52a1\u793a\u4f8b<\/h4>\n<p>\/\/ \u793a\u4f8b5: gRPC \u670d\u52a1\u7aef<br \/>\npackage main<br \/>\nimport (<br \/>\n    &#034;context&#034;<br \/>\n    &#034;log&#034;<br \/>\n    &#034;net&#034;<br \/>\n    &#034;google.golang.org\/grpc&#034;<br \/>\n    pb &#034;path\/to\/your\/proto&#034;<br \/>\n)<br \/>\ntype server struct {<br \/>\n    pb.UnimplementedGreeterServer<br \/>\n}<br \/>\nfunc (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {<br \/>\n    return &amp;pb.HelloReply{Message: &#034;Hello &#034; &#043; in.Name}, nil<br \/>\n}<br \/>\nfunc main() {<br \/>\n    lis, _ :&#061; net.Listen(&#034;tcp&#034;, &#034;:50051&#034;)<br \/>\n    s :&#061; grpc.NewServer()<br \/>\n    pb.RegisterGreeterServer(s, &amp;server{})<br \/>\n    s.Serve(lis)<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u6570\u636e\u7ed3\u6784\u793a\u4f8b<\/h4>\n<p>\/\/ \u793a\u4f8b6: \u81ea\u5b9a\u4e49Map\u7c7b\u578b<br \/>\npackage main<br \/>\nimport &#034;fmt&#034;<br \/>\ntype VoloMap map[string]interface{}<br \/>\nfunc (m VoloMap) Get(key string) interface{} {<br \/>\n    return m[key]<br \/>\n}<br \/>\nfunc main() {<br \/>\n    vm :&#061; make(VoloMap)<br \/>\n    vm[&#034;test&#034;] &#061; 123<br \/>\n    fmt.Println(vm.Get(&#034;test&#034;))<br \/>\n}<\/p>\n<p>\u5b8c\u6574 20\u4e2a\u793a\u4f8b\u5efa\u8bae\u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f\u83b7\u53d6&#xff1a;<\/p>\n<li>\u8bbf\u95ee GitHub \u641c\u7d22 volo-go-examples \u6216 go-volo<\/li>\n<li>\u53c2\u8003\u5b98\u65b9\u6587\u6863 https:\/\/pkg.go.dev\/github.com\/volo-labs<\/li>\n<li>\u4f7f\u7528 go get github.com\/volo-labs\/examples \u83b7\u53d6\u4ee3\u7801\u5e93<\/li>\n<p>&#xff08;\u6ce8&#xff1a;\u5b9e\u9645\u5f00\u53d1\u4e2d\u9700\u6839\u636e\u5177\u4f53\u4e1a\u52a1\u9700\u6c42\u8c03\u6574\u4ee3\u7801&#xff0c;\u4ee5\u4e0a\u793a\u4f8b\u4e3a\u901a\u7528\u6a21\u5f0f\u6f14\u793a&#xff09;<\/p>\n<h3 style=\"background-color:transparent\">Go \u7684 volo-labs<\/h3>\n<p>Go \u7684 volo-labs \u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u793a\u4f8b\u4ee3\u7801&#xff0c;\u6db5\u76d6\u57fa\u7840\u5230\u9ad8\u7ea7\u7528\u6cd5\u3002\u4ee5\u4e0b\u662f\u7cbe\u9009\u768420\u4e2a\u5b9e\u4f8b\u5206\u7c7b&#xff0c;\u5e2e\u52a9\u5feb\u901f\u638c\u63e1\u5176\u6838\u5fc3\u529f\u80fd\u3002<\/p>\n<h4 style=\"background-color:transparent\">\u57fa\u7840\u793a\u4f8b<\/h4>\n<li>Hello World<\/li>\n<p>package main<br \/>\nimport &#034;fmt&#034;<br \/>\nfunc main() {<br \/>\n    fmt.Println(&#034;Hello, volo-labs!&#034;)<br \/>\n}<\/p>\n<li>\u53d8\u91cf\u58f0\u660e\u4e0e\u521d\u59cb\u5316<\/li>\n<p>var name string &#061; &#034;volo&#034;<br \/>\nage :&#061; 25<\/p>\n<li>\u5e38\u91cf\u5b9a\u4e49<\/li>\n<p>const PI &#061; 3.14159<\/p>\n<h4>\u6570\u636e\u7ed3\u6784<\/h4>\n<li>\u6570\u7ec4\u64cd\u4f5c<\/li>\n<p>arr :&#061; [3]int{1, 2, 3}<br \/>\nfmt.Println(arr[0])<\/p>\n<li>\u5207\u7247\u52a8\u6001\u6269\u5c55<\/li>\n<p>slice :&#061; []int{1, 2}<br \/>\nslice &#061; append(slice, 3)<\/p>\n<li>Map\u952e\u503c\u5bf9<\/li>\n<p>m :&#061; map[string]int{&#034;a&#034;: 1}<br \/>\nm[&#034;b&#034;] &#061; 2<\/p>\n<h4>\u51fd\u6570\u4e0e\u65b9\u6cd5<\/h4>\n<li>\u591a\u8fd4\u56de\u503c\u51fd\u6570<\/li>\n<p>func swap(a, b int) (int, int) {<br \/>\n    return b, a<br \/>\n}<\/p>\n<li>\u95ed\u5305\u5e94\u7528<\/li>\n<p>func adder() func(int) int {<br \/>\n    sum :&#061; 0<br \/>\n    return func(x int) int {<br \/>\n        sum &#043;&#061; x<br \/>\n        return sum<br \/>\n    }<br \/>\n}<\/p>\n<h4>\u5e76\u53d1\u7f16\u7a0b<\/h4>\n<li>Goroutine\u542f\u52a8<\/li>\n<p>go func() {<br \/>\n    fmt.Println(&#034;\u5f02\u6b65\u6267\u884c&#034;)<br \/>\n}()<\/p>\n<li>Channel\u901a\u4fe1<\/li>\n<p>ch :&#061; make(chan string)<br \/>\ngo func() { ch &lt;- &#034;\u6d88\u606f&#034; }()<br \/>\nmsg :&#061; &lt;-ch<\/p>\n<h4>\u9519\u8bef\u5904\u7406<\/h4>\n<li>\u9519\u8bef\u8fd4\u56de\u68c0\u67e5<\/li>\n<p>result, err :&#061; someFunction()<br \/>\nif err !&#061; nil {<br \/>\n    log.Fatal(err)<br \/>\n}<\/p>\n<li>\u81ea\u5b9a\u4e49\u9519\u8bef\u7c7b\u578b<\/li>\n<p>type MyError struct{ Msg string }<br \/>\nfunc (e *MyError) Error() string { return e.Msg }<\/p>\n<h4>\u6587\u4ef6\u64cd\u4f5c<\/h4>\n<li>\u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9<\/li>\n<p>data, err :&#061; os.ReadFile(&#034;test.txt&#034;)<\/p>\n<li>\u5199\u5165\u6587\u4ef6<\/li>\n<p>err :&#061; os.WriteFile(&#034;output.txt&#034;, []byte(&#034;\u5185\u5bb9&#034;), 0644)<\/p>\n<h4>\u7f51\u7edc\u7f16\u7a0b<\/h4>\n<li>HTTP\u670d\u52a1\u5668<\/li>\n<p>http.HandleFunc(&#034;\/&#034;, func(w http.ResponseWriter, r *http.Request) {<br \/>\n    w.Write([]byte(&#034;\u54cd\u5e94&#034;))<br \/>\n})<br \/>\nhttp.ListenAndServe(&#034;:8080&#034;, nil)<\/p>\n<li>HTTP\u5ba2\u6237\u7aef\u8bf7\u6c42<\/li>\n<p>resp, err :&#061; http.Get(&#034;https:\/\/example.com&#034;)<\/p>\n<h4>\u6d4b\u8bd5\u4e0e\u6027\u80fd<\/h4>\n<li>\u5355\u5143\u6d4b\u8bd5\u793a\u4f8b<\/li>\n<p>func TestAdd(t *testing.T) {<br \/>\n    result :&#061; Add(2, 3)<br \/>\n    if result !&#061; 5 {<br \/>\n        t.Errorf(&#034;\u9884\u671f5&#xff0c;\u5f97\u5230%d&#034;, result)<br \/>\n    }<br \/>\n}<\/p>\n<li>\u57fa\u51c6\u6d4b\u8bd5<\/li>\n<p>func BenchmarkLoop(b *testing.B) {<br \/>\n    for i :&#061; 0; i &lt; b.N; i&#043;&#043; {<br \/>\n        _ &#061; i * i<br \/>\n    }<br \/>\n}<\/p>\n<h4>\u9ad8\u7ea7\u7279\u6027<\/h4>\n<li>\u53cd\u5c04\u83b7\u53d6\u7c7b\u578b<\/li>\n<p>t :&#061; reflect.TypeOf(42)<br \/>\nfmt.Println(t.Kind())<\/p>\n<li>JSON\u5e8f\u5217\u5316<\/li>\n<p>data :&#061; map[string]interface{}{&#034;name&#034;: &#034;volo&#034;}<br \/>\njsonStr, _ :&#061; json.Marshal(data)<\/p>\n<p>\u4ee5\u4e0b\u662f\u901a\u8fc7 Rust \u7ed3\u5408 SQLx \u548c Diesel \u5b9e\u73b0 CRUD \u64cd\u4f5c\u7684 10 \u4e2a\u5b9e\u7528\u793a\u4f8b&#xff0c;\u6db5\u76d6\u57fa\u672c\u64cd\u4f5c\u548c\u5e38\u89c1\u573a\u666f\u3002\u793a\u4f8b\u5206\u4e3a\u4e24\u90e8\u5206&#xff1a;SQLx&#xff08;\u5f02\u6b65&#xff09;\u548c Diesel&#xff08;\u540c\u6b65&#xff09;&#xff0c;\u4f7f\u7528 PostgreSQL \u6570\u636e\u5e93\u4f5c\u4e3a\u793a\u4f8b\u3002<\/p>\n<hr \/>\n<h3 style=\"background-color:transparent\">SQLx \u5b9e\u73b0 CRUD \u793a\u4f8b<\/h3>\n<h4>\u521d\u59cb\u5316\u8fde\u63a5\u6c60<\/h4>\n<p>use sqlx::postgres::PgPoolOptions;<\/p>\n<p>async fn init_pool() -&gt; sqlx::Result&lt;sqlx::PgPool&gt; {<br \/>\n    PgPoolOptions::new()<br \/>\n        .max_connections(5)<br \/>\n        .connect(&#034;postgres:\/\/user:pass&#064;localhost\/db&#034;).await<br \/>\n}<\/p>\n<h5>\u521b\u5efa\u8868\u7ed3\u6784<\/h5>\n<p>CREATE TABLE users (<br \/>\n    id SERIAL PRIMARY KEY,<br \/>\n    name VARCHAR NOT NULL,<br \/>\n    email VARCHAR UNIQUE NOT NULL<br \/>\n);<\/p>\n<h5>1. \u63d2\u5165\u6570\u636e<\/h5>\n<p>async fn create_user(pool: &amp;sqlx::PgPool, name: &amp;str, email: &amp;str) -&gt; sqlx::Result&lt;i32&gt; {<br \/>\n    let id &#061; sqlx::query!(<br \/>\n        &#034;INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id&#034;,<br \/>\n        name,<br \/>\n        email<br \/>\n    )<br \/>\n    .fetch_one(pool)<br \/>\n    .await?<br \/>\n    .id;<br \/>\n    Ok(id)<br \/>\n}<\/p>\n<h5>2. \u67e5\u8be2\u5355\u6761\u8bb0\u5f55<\/h5>\n<p>async fn get_user(pool: &amp;sqlx::PgPool, id: i32) -&gt; sqlx::Result&lt;Option&lt;(i32, String, String)&gt;&gt; {<br \/>\n    sqlx::query_as!(User, &#034;SELECT * FROM users WHERE id &#061; $1&#034;, id)<br \/>\n        .fetch_optional(pool)<br \/>\n        .await<br \/>\n}<\/p>\n<h5>3. \u6279\u91cf\u67e5\u8be2<\/h5>\n<p>async fn list_users(pool: &amp;sqlx::PgPool) -&gt; sqlx::Result&lt;Vec&lt;(i32, String, String)&gt;&gt; {<br \/>\n    sqlx::query_as!(User, &#034;SELECT * FROM users&#034;)<br \/>\n        .fetch_all(pool)<br \/>\n        .await<br \/>\n}<\/p>\n<h5>4. \u66f4\u65b0\u6570\u636e<\/h5>\n<p>async fn update_user(pool: &amp;sqlx::PgPool, id: i32, new_name: &amp;str) -&gt; sqlx::Result&lt;u64&gt; {<br \/>\n    let rows_affected &#061; sqlx::query!(<br \/>\n        &#034;UPDATE users SET name &#061; $1 WHERE id &#061; $2&#034;,<br \/>\n        new_name,<br \/>\n        id<br \/>\n    )<br \/>\n    .execute(pool)<br \/>\n    .await?<br \/>\n    .rows_affected();<br \/>\n    Ok(rows_affected)<br \/>\n}<\/p>\n<h5>5. \u5220\u9664\u6570\u636e<\/h5>\n<p>async fn delete_user(pool: &amp;sqlx::PgPool, id: i32) -&gt; sqlx::Result&lt;u64&gt; {<br \/>\n    sqlx::query!(&#034;DELETE FROM users WHERE id &#061; $1&#034;, id)<br \/>\n        .execute(pool)<br \/>\n        .await<br \/>\n        .map(|res| res.rows_affected())<br \/>\n}<\/p>\n<h4>Diesel \u5b9e\u73b0 CRUD \u793a\u4f8b<\/h4>\n<h5>\u521d\u59cb\u5316\u8fde\u63a5<\/h5>\n<p>use diesel::prelude::*;<br \/>\nuse diesel::pg::PgConnection;<\/p>\n<p>fn establish_connection() -&gt; PgConnection {<br \/>\n    PgConnection::establish(&#034;postgres:\/\/user:pass&#064;localhost\/db&#034;)<br \/>\n        .expect(&#034;Failed to connect to database&#034;)<br \/>\n}<\/p>\n<h5>\u5b9a\u4e49\u6a21\u578b<\/h5>\n<p>#[derive(Queryable, Insertable)]<br \/>\n#[diesel(table_name &#061; users)]<br \/>\nstruct User {<br \/>\n    id: i32,<br \/>\n    name: String,<br \/>\n    email: String,<br \/>\n}<\/p>\n<h5>6. \u63d2\u5165\u6570\u636e<\/h5>\n<p>fn diesel_create_user(conn: &amp;mut PgConnection, name: &amp;str, email: &amp;str) -&gt; User {<br \/>\n    diesel::insert_into(users::table)<br \/>\n        .values((users::name.eq(name), users::email.eq(email)))<br \/>\n        .returning(User::as_returning())<br \/>\n        .get_result(conn)<br \/>\n        .expect(&#034;Error inserting user&#034;)<br \/>\n}<\/p>\n<h5>7. \u6761\u4ef6\u67e5\u8be2<\/h5>\n<p>fn diesel_find_user(conn: &amp;mut PgConnection, target_id: i32) -&gt; Option&lt;User&gt; {<br \/>\n    users::table<br \/>\n        .filter(users::id.eq(target_id))<br \/>\n        .first(conn)<br \/>\n        .optional()<br \/>\n        .expect(&#034;Error querying user&#034;)<br \/>\n}<\/p>\n<h5>8. \u5206\u9875\u67e5\u8be2<\/h5>\n<p>fn diesel_paginate_users(conn: &amp;mut PgConnection, page: i64, per_page: i64) -&gt; Vec&lt;User&gt; {<br \/>\n    users::table<br \/>\n        .limit(per_page)<br \/>\n        .offset((page &#8211; 1) * per_page)<br \/>\n        .load(conn)<br \/>\n        .expect(&#034;Error loading users&#034;)<br \/>\n}<\/p>\n<h5>9. \u4e8b\u52a1\u64cd\u4f5c<\/h5>\n<p>fn diesel_transaction(conn: &amp;mut PgConnection) -&gt; Result&lt;(), diesel::result::Error&gt; {<br \/>\n    conn.transaction(|tx| {<br \/>\n        diesel::update(users::table)<br \/>\n            .set(users::name.eq(&#034;New Name&#034;))<br \/>\n            .execute(tx)?;<br \/>\n        diesel::delete(users::table.filter(users::id.eq(1)))<br \/>\n            .execute(tx)?;<br \/>\n        Ok(())<br \/>\n    })<br \/>\n}<\/p>\n<h5>10. \u5173\u8054\u67e5\u8be2<\/h5>\n<p>#[derive(Queryable)]<br \/>\nstruct PostWithAuthor {<br \/>\n    post_title: String,<br \/>\n    user_name: String,<br \/>\n}<\/p>\n<p>fn diesel_join_query(conn: &amp;mut PgConnection) -&gt; Vec&lt;PostWithAuthor&gt; {<br \/>\n    posts::table<br \/>\n        .inner_join(users::table)<br \/>\n        .select((posts::title, users::name))<br \/>\n        .load(conn)<br \/>\n        .expect(&#034;Error loading joined data&#034;)<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u5173\u952e\u5dee\u5f02\u603b\u7ed3<\/h4>\n<ul>\n<li>SQLx&#xff1a;\u5f02\u6b65\u9a71\u52a8&#xff0c;\u76f4\u63a5\u5199 SQL \u8bed\u53e5&#xff0c;\u9002\u5408\u9700\u8981\u7cbe\u7ec6\u63a7\u5236 SQL \u7684\u573a\u666f\u3002<\/li>\n<li>Diesel&#xff1a;\u540c\u6b65 ORM&#xff0c;\u63d0\u4f9b\u7c7b\u578b\u5b89\u5168\u7684\u67e5\u8be2\u6784\u5efa\u5668&#xff0c;\u9002\u5408\u590d\u6742\u4e1a\u52a1\u903b\u8f91\u3002<\/li>\n<\/ul>\n<p>\u4e24\u79cd\u65b9\u5f0f\u5747\u9700\u5728 Cargo.toml \u4e2d\u6dfb\u52a0\u5bf9\u5e94\u4f9d\u8d56\u3002\u5b9e\u9645\u9879\u76ee\u4e2d\u53ef\u6839\u636e\u56e2\u961f\u504f\u597d\u548c\u6027\u80fd\u9700\u6c42\u9009\u62e9\u65b9\u6848\u3002<\/p>\n<\/p>\n<h3 style=\"background-color:transparent\">\u83b7\u53d6KubeWharf\u5b9e\u4f8b<\/h3>\n<p>KubeWharf\u662f\u4e00\u4e2a\u5f00\u6e90\u7684Kubernetes\u591a\u79df\u6237\u7ba1\u7406\u7cfb\u7edf&#xff0c;\u7531\u5b57\u8282\u8df3\u52a8\u5f00\u53d1\u3002\u8981\u83b7\u53d6100\u4e2a\u5177\u4f53\u7684\u5b9e\u4f8b\u6216\u4f7f\u7528\u6848\u4f8b&#xff0c;\u53ef\u4ee5\u53c2\u8003\u5b98\u65b9\u6587\u6863\u3001GitHub\u4ed3\u5e93\u4ee5\u53ca\u793e\u533a\u8d21\u732e\u7684\u793a\u4f8b\u3002<\/p>\n<h4>\u5b98\u65b9\u6587\u6863\u548cGitHub\u4ed3\u5e93<\/h4>\n<p>KubeWharf\u7684GitHub\u4ed3\u5e93\u548c\u5b98\u65b9\u6587\u6863\u662f\u6700\u6743\u5a01\u7684\u8d44\u6e90&#xff0c;\u63d0\u4f9b\u4e86\u8be6\u7ec6\u7684\u5b89\u88c5\u3001\u914d\u7f6e\u548c\u4f7f\u7528\u793a\u4f8b\u3002\u8bbf\u95eeGitHub\u4ed3\u5e93\u53ef\u4ee5\u627e\u5230\u5404\u79cd\u90e8\u7f72\u6a21\u677f\u548c\u914d\u7f6e\u793a\u4f8b\u3002<\/p>\n<p>https:\/\/github.com\/kubewharf<\/p>\n<h4>\u793e\u533a\u548c\u8bba\u575b<\/h4>\n<p>Kubernetes\u548cKubeWharf\u7684\u793e\u533a\u8bba\u575b\u3001Slack\u9891\u9053\u6216Discord\u7fa4\u7ec4\u4e2d&#xff0c;\u7528\u6237\u7ecf\u5e38\u5206\u4eab\u5b9e\u9645\u4f7f\u7528\u6848\u4f8b\u3002\u53c2\u4e0e\u8fd9\u4e9b\u793e\u533a\u53ef\u4ee5\u83b7\u53d6\u5927\u91cf\u5b9e\u6218\u7ecf\u9a8c\u3002<\/p>\n<p>https:\/\/kubernetes.io\/community\/<\/p>\n<h4>\u535a\u5ba2\u548c\u6280\u672f\u6587\u7ae0<\/h4>\n<p>\u8bb8\u591a\u6280\u672f\u535a\u5ba2\u548c\u7f51\u7ad9\u4f1a\u53d1\u5e03\u5173\u4e8eKubeWharf\u7684\u6559\u7a0b\u548c\u6848\u4f8b\u7814\u7a76\u3002\u641c\u7d22\u5173\u952e\u8bcd\u201cKubeWharf examples\u201d\u6216\u201cKubeWharf use cases\u201d\u53ef\u4ee5\u627e\u5230\u76f8\u5173\u6587\u7ae0\u3002<\/p>\n<h4>\u89c6\u9891\u6559\u7a0b<\/h4>\n<p>YouTube\u6216\u5176\u4ed6\u6280\u672f\u89c6\u9891\u5e73\u53f0\u4e0a\u6709\u8bb8\u591a\u5173\u4e8eKubeWharf\u7684\u6559\u7a0b&#xff0c;\u6db5\u76d6\u4ece\u57fa\u7840\u5230\u9ad8\u7ea7\u7684\u591a\u79cd\u7528\u4f8b\u3002\u89c2\u770b\u8fd9\u4e9b\u89c6\u9891\u53ef\u4ee5\u76f4\u89c2\u5730\u5b66\u4e60\u5b9e\u9645\u5e94\u7528\u3002<\/p>\n<p>https:\/\/www.youtube.com\/results?search_query&#061;KubeWharf<\/p>\n<h4>\u5f00\u6e90\u9879\u76ee\u8d21\u732e<\/h4>\n<p>\u53c2\u4e0eKubeWharf\u7684\u5f00\u6e90\u9879\u76ee&#xff0c;\u67e5\u770b\u5176\u4ed6\u8d21\u732e\u8005\u63d0\u4ea4\u7684\u4ee3\u7801\u548c\u793a\u4f8b\u3002\u901a\u8fc7Pull Request\u548cIssue\u8ba8\u8bba&#xff0c;\u53ef\u4ee5\u5b66\u4e60\u5230\u66f4\u591a\u5b9e\u9645\u5e94\u7528\u573a\u666f\u3002<\/p>\n<p>https:\/\/github.com\/kubewharf\/kubeadmiral<\/p>\n<h4 style=\"background-color:transparent\">\u4f01\u4e1a\u6848\u4f8b\u7814\u7a76<\/h4>\n<p>\u4e00\u4e9b\u4f01\u4e1a\u4f1a\u516c\u5f00\u5206\u4eab\u4ed6\u4eec\u4f7f\u7528KubeWharf\u7684\u7ecf\u9a8c\u548c\u6848\u4f8b\u3002\u67e5\u627e\u8fd9\u4e9b\u6848\u4f8b\u7814\u7a76\u53ef\u4ee5\u83b7\u5f97\u5927\u89c4\u6a21\u90e8\u7f72\u7684\u5b9e\u6218\u7ecf\u9a8c\u3002<\/p>\n<h3>\u9002\u7528\u4e8eRust Web\u5f00\u53d1<\/h3>\n<p>\u4ee5\u4e0b\u662f\u9002\u7528\u4e8eRust Web\u5f00\u53d1\u7684\u811a\u624b\u67b6\u5b9e\u4f8b&#xff0c;\u6db5\u76d6\u4e0d\u540c\u6846\u67b6\u548c\u573a\u666f\u7684\u5b9e\u7528\u6848\u4f8b\u3002\u6bcf\u4e2a\u4f8b\u5b50\u5747\u9644\u5173\u952e\u4ee3\u7801\u7247\u6bb5\u6216\u914d\u7f6e\u8bf4\u660e&#xff0c;\u53ef\u76f4\u63a5\u4f5c\u4e3a\u9879\u76ee\u6a21\u677f\u4f7f\u7528\u3002<\/p>\n<h4 style=\"background-color:transparent\">\u57fa\u7840HTTP\u670d\u52a1\u5668&#xff08;axum&#xff09;<\/h4>\n<p>use axum::{Router, routing::get};<br \/>\nasync fn handler() -&gt; &amp;&#039;static str { &#034;Hello Axum!&#034; }<br \/>\n#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let app &#061; Router::new().route(&#034;\/&#034;, get(handler));<br \/>\n    axum::Server::bind(&amp;&#034;0.0.0.0:3000&#034;.parse().unwrap())<br \/>\n        .serve(app.into_make_service())<br \/>\n        .await.unwrap();<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u9759\u6001\u6587\u4ef6\u670d\u52a1&#xff08;rocket&#xff09;<\/h4>\n<p>#[macro_use] extern crate rocket;<br \/>\nuse rocket::fs::FileServer;<br \/>\n#[launch]<br \/>\nfn rocket() -&gt; _ {<br \/>\n    rocket::build().mount(&#034;\/static&#034;, FileServer::from(&#034;static\/&#034;))<br \/>\n}<\/p>\n<h4>RESTful API&#xff08;actix-web&#xff09;<\/h4>\n<p>use actix_web::{web, App, HttpResponse, HttpServer};<br \/>\nasync fn index() -&gt; HttpResponse {<br \/>\n    HttpResponse::Ok().body(&#034;API ready&#034;)<br \/>\n}<br \/>\n#[actix_web::main]<br \/>\nasync fn main() -&gt; std::io::Result&lt;()&gt; {<br \/>\n    HttpServer::new(|| App::new().route(&#034;\/&#034;, web::get().to(index)))<br \/>\n        .bind(&#034;127.0.0.1:8080&#034;)?<br \/>\n        .run()<br \/>\n        .await<br \/>\n}<\/p>\n<h4>WebSocket\u804a\u5929\u5ba4&#xff08;warp&#xff09;<\/h4>\n<p>use warp::Filter;<br \/>\nasync fn ws_handler(ws: warp::ws::Ws) {<br \/>\n    \/\/ WebSocket\u8fde\u63a5\u5904\u7406\u903b\u8f91<br \/>\n}<br \/>\n#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let ws_route &#061; warp::path(&#034;chat&#034;).and(warp::ws()).map(ws_handler);<br \/>\n    warp::serve(ws_route).run(([127, 0, 0, 1], 3030)).await;<br \/>\n}<\/p>\n<h4>JWT\u8ba4\u8bc1\u4e2d\u95f4\u4ef6&#xff08;poem&#xff09;<\/h4>\n<p>use poem::{get, middleware::JwtAuth, Route};<br \/>\nasync fn protected() -&gt; &amp;&#039;static str { &#034;Secret content&#034; }<br \/>\n#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let app &#061; Route::new()<br \/>\n        .at(&#034;\/&#034;, get(protected))<br \/>\n        .with(JwtAuth::new(&#034;secret_key&#034;));<br \/>\n    poem::Server::bind(&#034;0.0.0.0:3000&#034;).run(app).await.unwrap();<br \/>\n}<\/p>\n<h4>\u6570\u636e\u5e93\u8fde\u63a5\u6c60&#xff08;sqlx &#043; actix&#xff09;<\/h4>\n<p>use sqlx::postgres::PgPoolOptions;<br \/>\n#[actix_web::main]<br \/>\nasync fn main() -&gt; Result&lt;(), sqlx::Error&gt; {<br \/>\n    let pool &#061; PgPoolOptions::new()<br \/>\n        .connect(&#034;postgres:\/\/user:pass&#064;localhost\/db&#034;).await?;<br \/>\n    \/\/ \u4f7f\u7528pool\u8fdb\u884c\u6570\u636e\u5e93\u64cd\u4f5c<br \/>\n    Ok(())<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">GraphQL\u670d\u52a1&#xff08;async-graphql &#043; warp&#xff09;<\/h4>\n<p>use async_graphql::{Schema, EmptyMutation, EmptySubscription};<br \/>\nstruct QueryRoot;<br \/>\n#[Object]<br \/>\nimpl QueryRoot { async fn version(&amp;self) -&gt; &amp;str { &#034;1.0&#034; } }<br \/>\n#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let schema &#061; Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish();<br \/>\n    let graphql_post &#061; warp::path(&#034;graphql&#034;).and(async_graphql_warp::graphql(schema));<br \/>\n    warp::serve(graphql_post).run(([127, 0, 0, 1], 8000)).await;<br \/>\n}<\/p>\n<h4>\u6587\u4ef6\u4e0a\u4f20&#xff08;tide&#xff09;<\/h4>\n<p>use tide::Request;<br \/>\nasync fn upload(mut req: Request&lt;()&gt;) -&gt; tide::Result&lt;String&gt; {<br \/>\n    let file &#061; req.body_file(&#034;file&#034;).await?;<br \/>\n    Ok(format!(&#034;Saved: {:?}&#034;, file))<br \/>\n}<br \/>\n#[async_std::main]<br \/>\nasync fn main() -&gt; tide::Result&lt;()&gt; {<br \/>\n    let mut app &#061; tide::new();<br \/>\n    app.at(&#034;\/upload&#034;).post(upload);<br \/>\n    app.listen(&#034;127.0.0.1:8080&#034;).await?;<br \/>\n    Ok(())<br \/>\n}<\/p>\n<h4>\u6a21\u677f\u6e32\u67d3&#xff08;askama &#043; rocket&#xff09;<\/h4>\n<p>#[macro_use] extern crate rocket;<br \/>\nuse askama::Template;<br \/>\n#[derive(Template)]<br \/>\n#[template(path &#061; &#034;index.html&#034;)]<br \/>\nstruct IndexTemplate { title: String }<br \/>\n#[get(&#034;\/&#034;)]<br \/>\nfn index() -&gt; IndexTemplate {<br \/>\n    IndexTemplate { title: &#034;Home&#034;.into() }<br \/>\n}<br \/>\n#[launch]<br \/>\nfn rocket() -&gt; _ {<br \/>\n    rocket::build().mount(&#034;\/&#034;, routes![index])<br \/>\n}<\/p>\n<h4>\u5065\u5eb7\u68c0\u67e5&#xff08;actix-web&#xff09;<\/h4>\n<p>use actix_web::{get, App, HttpResponse, HttpServer};<br \/>\n#[get(&#034;\/health&#034;)]<br \/>\nasync fn health() -&gt; HttpResponse {<br \/>\n    HttpResponse::Ok().json(&#034;OK&#034;)<br \/>\n}<br \/>\n#[actix_web::main]<br \/>\nasync fn main() -&gt; std::io::Result&lt;()&gt; {<br \/>\n    HttpServer::new(|| App::new().service(health))<br \/>\n        .bind(&#034;127.0.0.1:8080&#034;)?<br \/>\n        .run()<br \/>\n        .await<br \/>\n}<\/p>\n<h4>\u914d\u7f6e\u7ba1\u7406&#xff08;config &#043; serde&#xff09;<\/h4>\n<p>use config::Config;<br \/>\n#[derive(serde::Deserialize)]<br \/>\nstruct Settings { database_url: String }<br \/>\nfn load_config() -&gt; Settings {<br \/>\n    Config::builder()<br \/>\n        .add_source(config::File::with_name(&#034;config&#034;))<br \/>\n        .build().unwrap()<br \/>\n        .try_deserialize().unwrap()<br \/>\n}<\/p>\n<h4>\u65e5\u5fd7\u8bb0\u5f55&#xff08;tracing &#043; axum&#xff09;<\/h4>\n<p>use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};<br \/>\n#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    tracing_subscriber::registry()<br \/>\n        .with(tracing_subscriber::fmt::layer())<br \/>\n        .init();<br \/>\n    \/\/ \u542f\u52a8axum\u670d\u52a1<br \/>\n}<\/p>\n<h4>\u4efb\u52a1\u961f\u5217&#xff08;bb8 &#043; redis&#xff09;<\/h4>\n<p>use bb8_redis::RedisConnectionManager;<br \/>\nasync fn create_pool() -&gt; bb8::Pool&lt;RedisConnectionManager&gt; {<br \/>\n    let manager &#061; RedisConnectionManager::new(&#034;redis:\/\/localhost&#034;).unwrap();<br \/>\n    bb8::Pool::builder().build(manager).await.unwrap()<br \/>\n}<\/p>\n<h4>\u6d4b\u8bd5\u811a\u624b\u67b6&#xff08;tokio-test&#xff09;<\/h4>\n<p>#[tokio::test]<br \/>\nasync fn test_handler() {<br \/>\n    let response &#061; handler().await;<br \/>\n    assert_eq!(response, &#034;Hello Axum!&#034;);<br \/>\n}<\/p>\n<h4>\u8de8\u57df\u5904\u7406&#xff08;actix-cors&#xff09;<\/h4>\n<p>use actix_cors::Cors;<br \/>\nApp::new().wrap(<br \/>\n    Cors::default()<br \/>\n        .allow_any_origin()<br \/>\n        .allowed_methods(vec![&#034;GET&#034;, &#034;POST&#034;])<br \/>\n)<\/p>\n<h4>\u547d\u4ee4\u884c\u53c2\u6570&#xff08;clap&#xff09;<\/h4>\n<p>use clap::Parser;<br \/>\n#[derive(Parser)]<br \/>\nstruct Args { port: u16 }<br \/>\nlet args &#061; Args::parse();<br \/>\nprintln!(&#034;Server will run on port {}&#034;, args.port);<\/p>\n<h4>\u9519\u8bef\u5904\u7406&#xff08;thiserror &#043; axum&#xff09;<\/h4>\n<p>#[derive(thiserror::Error, Debug)]<br \/>\nenum ApiError { #[error(&#034;Not Found&#034;)] NotFound }<br \/>\nimpl IntoResponse for ApiError {<br \/>\n    fn into_response(self) -&gt; axum::response::Response {<br \/>\n        match self {<br \/>\n            Self::NotFound &#061;&gt; (StatusCode::NOT_FOUND, self.to_string()).into_response(),<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<h4>\u901f\u7387\u9650\u5236&#xff08;governor &#043; actix&#xff09;<\/h4>\n<p>use actix_governor::{Governor, GovernorConfigBuilder};<br \/>\nlet governor_conf &#061; GovernorConfigBuilder::default().per_second(2).burst_size(5).finish();<br \/>\nApp::new().wrap(Governor::new(&amp;governor_conf))<\/p>\n<h4>\u76d1\u63a7\u6307\u6807&#xff08;metrics &#043; prometheus&#xff09;<\/h4>\n<p>use metrics_exporter_prometheus::PrometheusBuilder;<br \/>\nPrometheusBuilder::new().install().unwrap();<br \/>\nmetrics::counter!(&#034;requests&#034;, 1);<\/p>\n<h4 style=\"background-color:transparent\">\u90e8\u7f72\u914d\u7f6e&#xff08;Dockerfile&#xff09;<\/h4>\n<p>FROM rust:1.70 as builder<br \/>\nWORKDIR \/app<br \/>\nCOPY . .<br \/>\nRUN cargo build &#8211;release<\/p>\n<p>FROM debian:bullseye-slim<br \/>\nCOPY &#8211;from&#061;builder \/app\/target\/release\/app \/usr\/local\/bin<br \/>\nCMD [&#034;\/usr\/local\/bin\/app&#034;]<\/p>\n<h3 style=\"background-color:transparent\">\u4f7f\u7528crossbeam\u8fdb\u884c\u7ebf\u7a0b\u95f4\u901a\u4fe1<\/h3>\n<p>\u521b\u5efa\u65e0\u9501\u961f\u5217&#xff0c;\u591a\u4e2a\u7ebf\u7a0b\u901a\u8fc7crossbeam::channel\u53d1\u9001\u548c\u63a5\u6536\u6570\u636e\u3002\u53d1\u9001\u65b9\u4f7f\u7528send\u65b9\u6cd5&#xff0c;\u63a5\u6536\u65b9\u4f7f\u7528recv\u6216try_recv\u65b9\u6cd5\u3002<\/p>\n<p>use crossbeam::channel;<br \/>\nlet (sender, receiver) &#061; channel::unbounded();<br \/>\nstd::thread::spawn(move || sender.send(42).unwrap());<br \/>\nassert_eq!(receiver.recv().unwrap(), 42);<\/p>\n<h4 style=\"background-color:transparent\">\u591a\u751f\u4ea7\u8005\u5355\u6d88\u8d39\u8005\u6a21\u5f0f<\/h4>\n<p>\u901a\u8fc7crossbeam::channel\u652f\u6301\u591a\u4e2a\u751f\u4ea7\u8005\u7ebf\u7a0b\u5411\u5355\u4e2a\u6d88\u8d39\u8005\u7ebf\u7a0b\u53d1\u9001\u6570\u636e\u3002<\/p>\n<p>let (sender, receiver) &#061; channel::unbounded();<br \/>\nfor i in 0..3 {<br \/>\n    let s &#061; sender.clone();<br \/>\n    std::thread::spawn(move || s.send(i).unwrap());<br \/>\n}<br \/>\nfor _ in 0..3 {<br \/>\n    println!(&#034;{}&#034;, receiver.recv().unwrap());<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u6709\u754c\u961f\u5217\u7684\u4f7f\u7528<\/h4>\n<p>\u521b\u5efa\u5bb9\u91cf\u9650\u5236\u7684\u961f\u5217&#xff0c;\u907f\u514d\u5185\u5b58\u65e0\u9650\u589e\u957f\u3002\u53d1\u9001\u64cd\u4f5c\u5728\u961f\u5217\u6ee1\u65f6\u4f1a\u963b\u585e\u3002<\/p>\n<p>let (sender, receiver) &#061; channel::bounded(2);<br \/>\nsender.send(1).unwrap();<br \/>\nsender.send(2).unwrap();<br \/>\nstd::thread::spawn(move || sender.send(3).unwrap());<\/p>\n<h4 style=\"background-color:transparent\">\u7ebf\u7a0b\u5b89\u5168\u7684\u65e0\u9501\u6808<\/h4>\n<p>\u4f7f\u7528crossbeam::epoch\u5b9e\u73b0\u65e0\u9501\u6570\u636e\u7ed3\u6784&#xff0c;\u5982\u6808\u3002\u901a\u8fc7\u539f\u5b50\u6307\u9488\u548c\u5783\u573e\u56de\u6536\u673a\u5236\u786e\u4fdd\u5b89\u5168\u3002<\/p>\n<p>use crossbeam::epoch::{self, Atomic, Owned};<br \/>\nlet stack &#061; Atomic::new(Stack::new());<br \/>\nepoch::pin(|scope| {<br \/>\n    stack.push(10, scope);<br \/>\n    assert_eq!(stack.pop(scope), Some(10));<br \/>\n});<\/p>\n<h4 style=\"background-color:transparent\">\u65e0\u9501\u961f\u5217\u7684\u539f\u5b50\u64cd\u4f5c<\/h4>\n<p>\u5229\u7528crossbeam::atomic::AtomicCell\u5b9e\u73b0\u7b80\u5355\u539f\u5b50\u64cd\u4f5c&#xff0c;\u66ff\u4ee3\u6807\u51c6\u5e93\u7684AtomicUsize\u3002<\/p>\n<p>use crossbeam::atomic::AtomicCell;<br \/>\nlet counter &#061; AtomicCell::new(0);<br \/>\ncounter.fetch_add(1);<br \/>\nassert_eq!(counter.load(), 1);<\/p>\n<h4>\u591a\u7ebf\u7a0b\u5e76\u884c\u8fed\u4ee3<\/h4>\n<p>crossbeam::scope\u521b\u5efa\u7ebf\u7a0b\u4f5c\u7528\u57df&#xff0c;\u786e\u4fdd\u6240\u6709\u7ebf\u7a0b\u5728\u4f5c\u7528\u57df\u7ed3\u675f\u524d\u5b8c\u6210\u3002<\/p>\n<p>let array &#061; [1, 2, 3];<br \/>\ncrossbeam::scope(|s| {<br \/>\n    for i in &amp;array {<br \/>\n        s.spawn(move |_| println!(&#034;{}&#034;, i));<br \/>\n    }<br \/>\n}).unwrap();<\/p>\n<h4 style=\"background-color:transparent\">\u7ebf\u7a0b\u6c60\u4efb\u52a1\u5206\u53d1<\/h4>\n<p>\u7ed3\u5408crossbeam::deque\u5b9e\u73b0\u5de5\u4f5c\u7a83\u53d6\u7ebf\u7a0b\u6c60\u3002\u4efb\u52a1\u4ece\u5168\u5c40\u961f\u5217\u6216\u5176\u4ed6\u7ebf\u7a0b\u961f\u5217\u7a83\u53d6\u3002<\/p>\n<p>use crossbeam::deque;<br \/>\nlet (worker, stealer) &#061; deque::fifo();<br \/>\nworker.push(&#034;task&#034;);<br \/>\nstd::thread::spawn(move || stealer.steal().unwrap());<\/p>\n<h4>\u65e0\u9501\u54c8\u5e0c\u8868\u7684\u5b9e\u73b0<\/h4>\n<p>\u901a\u8fc7crossbeam::epoch\u6784\u5efa\u5e76\u53d1\u54c8\u5e0c\u8868&#xff0c;\u652f\u6301\u9ad8\u5e76\u53d1\u7684\u63d2\u5165\u548c\u67e5\u8be2\u3002<\/p>\n<p>use crossbeam::epoch::{Guard, Atomic};<br \/>\nlet map &#061; Atomic::new(HashMap::new());<br \/>\nepoch::pin(|scope| {<br \/>\n    map.insert(&#034;key&#034;, &#034;value&#034;, scope);<br \/>\n    assert_eq!(map.get(&#034;key&#034;, scope), Some(&#034;value&#034;));<br \/>\n});<\/p>\n<h4>\u5e76\u53d1\u8ba1\u6570\u5668<\/h4>\n<p>\u4f7f\u7528crossbeam::sync::ShardedLock\u5b9e\u73b0\u9ad8\u6548\u7684\u8bfb\u5199\u5206\u79bb\u8ba1\u6570\u5668\u3002<\/p>\n<p>use crossbeam::sync::ShardedLock;<br \/>\nlet counter &#061; ShardedLock::new(0);<br \/>\n*counter.write().unwrap() &#043;&#061; 1;<br \/>\nassert_eq!(*counter.read().unwrap(), 1);<\/p>\n<h4 style=\"background-color:transparent\">\u7ebf\u7a0b\u95f4\u5171\u4eab\u6570\u636e<\/h4>\n<p>crossbeam::atomic::SharedArc\u5141\u8bb8\u8de8\u7ebf\u7a0b\u5171\u4eab\u6570\u636e&#xff0c;\u65e0\u9700\u751f\u547d\u5468\u671f\u6807\u6ce8\u3002<\/p>\n<p>use crossbeam::atomic::SharedArc;<br \/>\nlet shared &#061; SharedArc::new(42);<br \/>\nlet cloned &#061; shared.clone();<br \/>\nstd::thread::spawn(move || assert_eq!(*cloned, 42)).join().unwrap();<\/p>\n<h4>\u65e0\u9501\u94fe\u8868\u64cd\u4f5c<\/h4>\n<p>\u6784\u5efa\u7ebf\u7a0b\u5b89\u5168\u7684\u94fe\u8868&#xff0c;\u652f\u6301\u5e76\u53d1\u63d2\u5165\u548c\u5220\u9664\u3002\u4f9d\u8d56crossbeam::epoch\u7ba1\u7406\u5185\u5b58\u56de\u6536\u3002<\/p>\n<p>use crossbeam::epoch::{self, Atomic};<br \/>\nlet list &#061; Atomic::new(LinkedList::new());<br \/>\nepoch::pin(|scope| {<br \/>\n    list.push_front(1, scope);<br \/>\n    assert_eq!(list.pop_front(scope), Some(1));<br \/>\n});<\/p>\n<h4>\u5b9a\u65f6\u5668\u4e0e\u8d85\u65f6\u63a7\u5236<\/h4>\n<p>crossbeam::channel\u652f\u6301\u8d85\u65f6\u63a5\u6536\u64cd\u4f5c&#xff0c;\u907f\u514d\u65e0\u9650\u7b49\u5f85\u3002<\/p>\n<p>use std::time::Duration;<br \/>\nlet (sender, receiver) &#061; channel::bounded(1);<br \/>\nassert!(receiver.recv_timeout(Duration::from_millis(100)).is_err());<br \/>\nsender.send(1).unwrap();<br \/>\nassert_eq!(receiver.recv_timeout(Duration::from_millis(100)).unwrap(), 1);<\/p>\n<h4>\u5e76\u53d1\u7f13\u5b58\u7cfb\u7edf<\/h4>\n<p>\u5229\u7528crossbeam::sync::ShardedLock\u6784\u5efa\u8bfb\u5199\u5206\u79bb\u7684\u7f13\u5b58\u7ed3\u6784\u3002<\/p>\n<p>use crossbeam::sync::ShardedLock;<br \/>\nuse std::collections::HashMap;<br \/>\nlet cache &#061; ShardedLock::new(HashMap::new());<br \/>\ncache.write().unwrap().insert(&#034;key&#034;, &#034;value&#034;);<br \/>\nassert_eq!(cache.read().unwrap().get(&#034;key&#034;), Some(&amp;&#034;value&#034;));<\/p>\n<h4>\u65e0\u9501\u4efb\u52a1\u8c03\u5ea6\u5668<\/h4>\n<p>\u4f7f\u7528crossbeam::deque\u5b9e\u73b0\u4efb\u52a1\u8c03\u5ea6&#xff0c;\u652f\u6301\u5de5\u4f5c\u7a83\u53d6\u4ee5\u63d0\u9ad8\u5e76\u884c\u6548\u7387\u3002<\/p>\n<p>use crossbeam::deque;<br \/>\nlet (worker, stealer) &#061; deque::lifo();<br \/>\nworker.push(&#034;task1&#034;);<br \/>\nworker.push(&#034;task2&#034;);<br \/>\nstd::thread::spawn(move || stealer.steal_batch(&amp;worker));<\/p>\n<h4>\u5e76\u53d1\u4e8b\u4ef6\u603b\u7ebf<\/h4>\n<p>\u901a\u8fc7crossbeam::channel\u5b9e\u73b0\u591a\u8ba2\u9605\u8005\u7684\u4e8b\u4ef6\u53d1\u5e03-\u8ba2\u9605\u6a21\u578b\u3002<\/p>\n<p>let (sender, receiver) &#061; channel::unbounded();<br \/>\nlet subscriber &#061; receiver.clone();<br \/>\nstd::thread::spawn(move || subscriber.recv().unwrap());<br \/>\nsender.send(&#034;event&#034;).unwrap();<\/p>\n<h4>\u7ebf\u7a0b\u5b89\u5168\u7684\u5bf9\u8c61\u6c60<\/h4>\n<p>crossbeam::sync::SegQueue\u6784\u5efa\u53ef\u590d\u7528\u7684\u5bf9\u8c61\u6c60&#xff0c;\u51cf\u5c11\u5185\u5b58\u5206\u914d\u5f00\u9500\u3002<\/p>\n<p>use crossbeam::sync::SegQueue;<br \/>\nlet pool &#061; SegQueue::new();<br \/>\npool.push(&#034;object&#034;);<br \/>\nassert_eq!(pool.pop(), Some(&#034;object&#034;));<\/p>\n<h4>\u5e76\u884c\u6570\u7ec4\u5904\u7406<\/h4>\n<p>crossbeam::thread::scope\u5206\u5272\u6570\u7ec4\u7ed9\u591a\u4e2a\u7ebf\u7a0b\u5e76\u884c\u5904\u7406\u3002<\/p>\n<p>let mut array &#061; [1, 2, 3, 4];<br \/>\ncrossbeam::thread::scope(|s| {<br \/>\n    for elem in &amp;mut array {<br \/>\n        s.spawn(move |_| *elem &#043;&#061; 1);<br \/>\n    }<br \/>\n}).unwrap();<br \/>\nassert_eq!(array, [2, 3, 4, 5]);<\/p>\n<h4>\u975e\u963b\u585e\u6570\u636e\u7ed3\u6784<\/h4>\n<p>crossbeam::queue::ArrayQueue\u63d0\u4f9b\u56fa\u5b9a\u5927\u5c0f\u7684\u975e\u963b\u585e\u961f\u5217&#xff0c;\u9002\u5408\u9ad8\u5e76\u53d1\u573a\u666f\u3002<\/p>\n<p>use crossbeam::queue::ArrayQueue;<br \/>\nlet queue &#061; ArrayQueue::new(2);<br \/>\nqueue.push(1).unwrap();<br \/>\nassert_eq!(queue.pop(), Ok(1));<\/p>\n<h4>\u8de8\u7ebf\u7a0b\u9519\u8bef\u4f20\u9012<\/h4>\n<p>\u901a\u8fc7crossbeam::channel\u53d1\u9001Result\u7c7b\u578b&#xff0c;\u4f20\u9012\u5b50\u7ebf\u7a0b\u9519\u8bef\u5230\u4e3b\u7ebf\u7a0b\u3002<\/p>\n<p>let (sender, receiver) &#061; channel::unbounded();<br \/>\nstd::thread::spawn(move || sender.send(Err(&#034;error&#034;)).unwrap());<br \/>\nassert!(receiver.recv().unwrap().is_err());<\/p>\n<h4 style=\"background-color:transparent\">\u52a8\u6001\u7ebf\u7a0b\u6570\u8c03\u6574<\/h4>\n<p>crossbeam::thread::Scope\u52a8\u6001\u751f\u6210\u7ebf\u7a0b&#xff0c;\u6839\u636e\u8d1f\u8f7d\u8c03\u6574\u5e76\u884c\u5ea6\u3002<\/p>\n<p>let data &#061; vec![1, 2, 3];<br \/>\ncrossbeam::thread::scope(|s| {<br \/>\n    for item in data {<br \/>\n        s.spawn(move |_| println!(&#034;{}&#034;, item));<br \/>\n    }<br \/>\n}).unwrap();<\/p>\n<h3 style=\"background-color:transparent\">Rust\u6784\u5efa\u9ad8\u6027\u80fdHTTP\u670d\u52a1\u5668<\/h3>\n<p>\u4f7f\u7528Rust\u6784\u5efa\u9ad8\u6027\u80fdHTTP\u670d\u52a1\u5668&#xff0c;\u5982\u901a\u8fc7actix-web\u6216warp\u6846\u67b6\u5b9e\u73b0RESTful API\u3002<\/p>\n<p>use actix_web::{get, App, HttpServer, Responder};<\/p>\n<p>#[get(&#034;\/&#034;)]<br \/>\nasync fn index() -&gt; impl Responder {<br \/>\n    &#034;Hello, Rust Server!&#034;<br \/>\n}<\/p>\n<p>#[actix_web::main]<br \/>\nasync fn main() -&gt; std::io::Result&lt;()&gt; {<br \/>\n    HttpServer::new(|| App::new().service(index))<br \/>\n        .bind(&#034;127.0.0.1:8080&#034;)?<br \/>\n        .run()<br \/>\n        .await<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u6e38\u620f\u670d\u52a1\u5668<\/h4>\n<p>\u5229\u7528Rust\u7684\u5e76\u53d1\u7279\u6027\u5f00\u53d1\u591a\u4eba\u6e38\u620f\u670d\u52a1\u5668&#xff0c;\u5982\u4f7f\u7528tokio\u5904\u7406\u5b9e\u65f6\u73a9\u5bb6\u4ea4\u4e92\u3002<\/p>\n<p>use tokio::net::{TcpListener, TcpStream};<br \/>\nuse tokio::io::{AsyncReadExt, AsyncWriteExt};<\/p>\n<p>async fn handle_client(mut stream: TcpStream) {<br \/>\n    let mut buf &#061; [0; 1024];<br \/>\n    stream.read(&amp;mut buf).await.unwrap();<br \/>\n    stream.write_all(b&#034;Welcome to Rust Game Server!&#034;).await.unwrap();<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u5fae\u670d\u52a1\u67b6\u6784<\/h4>\n<p>\u6784\u5efa\u8f7b\u91cf\u7ea7\u5fae\u670d\u52a1&#xff0c;\u5982\u8ba2\u5355\u5904\u7406\u6216\u7528\u6237\u8ba4\u8bc1\u670d\u52a1&#xff0c;\u914d\u5408tonic\u5b9e\u73b0gRPC\u901a\u4fe1\u3002<\/p>\n<p>use tonic::{transport::Server, Request, Response, Status};<\/p>\n<p>pub mod order_service {<br \/>\n    tonic::include_proto!(&#034;orders&#034;);<br \/>\n}<\/p>\n<p>#[derive(Default)]<br \/>\npub struct OrderService;<\/p>\n<p>#[tonic::async_trait]<br \/>\nimpl order_server::Order for OrderService {<br \/>\n    async fn create_order(<br \/>\n        &amp;self,<br \/>\n        request: Request&lt;CreateOrderRequest&gt;,<br \/>\n    ) -&gt; Result&lt;Response&lt;OrderResponse&gt;, Status&gt; {<br \/>\n        Ok(Response::new(OrderResponse { id: 1 }))<br \/>\n    }<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u6570\u636e\u5e93\u4ee3\u7406<\/h4>\n<p>\u5f00\u53d1\u9ad8\u6027\u80fd\u6570\u636e\u5e93\u4e2d\u95f4\u4ef6&#xff0c;\u5982MySQL\u4ee3\u7406&#xff0c;\u4f7f\u7528mysql_async\u5e93\u4f18\u5316\u67e5\u8be2\u8def\u7531\u3002<\/p>\n<p>use mysql_async::prelude::*;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let pool &#061; mysql_async::Pool::new(&#034;mysql:\/\/user:pass&#064;localhost:3306\/db&#034;);<br \/>\n    let mut conn &#061; pool.get_conn().await.unwrap();<br \/>\n    conn.query_iter(&#034;SELECT * FROM users&#034;).await.unwrap();<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u5b9e\u65f6\u804a\u5929\u670d\u52a1\u5668<\/h4>\n<p>\u901a\u8fc7tokio-tungstenite\u5b9e\u73b0WebSocket\u804a\u5929\u670d\u52a1\u5668&#xff0c;\u652f\u6301\u4f4e\u5ef6\u8fdf\u6d88\u606f\u5e7f\u64ad\u3002<\/p>\n<p>use tokio_tungstenite::accept_async;<br \/>\nuse tokio::net::TcpListener;<\/p>\n<p>async fn handle_connection(stream: TcpStream) {<br \/>\n    let ws_stream &#061; accept_async(stream).await.unwrap();<br \/>\n    \/\/ \u5e7f\u64ad\u903b\u8f91<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">IoT\u6570\u636e\u805a\u5408<\/h4>\n<p>\u5904\u7406\u7269\u8054\u7f51\u8bbe\u5907\u6570\u636e&#xff0c;\u4f7f\u7528rumqttd\u642d\u5efaMQTT\u6d88\u606f\u4ee3\u7406\u3002<\/p>\n<p>use rumqttd::{Broker, Config};<\/p>\n<p>fn main() {<br \/>\n    let config &#061; Config::default();<br \/>\n    let mut broker &#061; Broker::new(config);<br \/>\n    broker.start().unwrap();<br \/>\n}<\/p>\n<h4>\u6587\u4ef6\u540c\u6b65\u670d\u52a1<\/h4>\n<p>\u6784\u5efaP2P\u6587\u4ef6\u540c\u6b65\u670d\u52a1\u5668&#xff0c;\u5982\u4f7f\u7528libp2p\u5b9e\u73b0\u8282\u70b9\u95f4\u6570\u636e\u4f20\u8f93\u3002<\/p>\n<p>use libp2p::{identity, PeerId, Swarm};<br \/>\nuse libp2p::swarm::SwarmEvent;<\/p>\n<p>let local_key &#061; identity::Keypair::generate_ed25519();<br \/>\nlet local_peer_id &#061; PeerId::from(local_key.public());<br \/>\nlet transport &#061; libp2p::development_transport(local_key).await.unwrap();<\/p>\n<h4>\u533a\u5757\u94fe\u8282\u70b9<\/h4>\n<p>\u5f00\u53d1\u533a\u5757\u94fe\u7f51\u7edc\u8282\u70b9&#xff0c;\u5982\u57fa\u4e8esubstrate\u6846\u67b6\u6784\u5efa\u81ea\u5b9a\u4e49\u94fe\u3002<\/p>\n<p>use sc_service::GenericChainSpec;<br \/>\nuse node_template_runtime::GenesisConfig;<\/p>\n<p>fn chain_spec() -&gt; Result&lt;GenericChainSpec&lt;GenesisConfig&gt;, String&gt; {<br \/>\n    GenericChainSpec::from_json_bytes(&amp;include_bytes!(&#034;..\/chain_spec.json&#034;)[..])<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u8d1f\u8f7d\u5747\u8861\u5668<\/h4>\n<p>\u5b9e\u73b0\u53cd\u5411\u4ee3\u7406\u670d\u52a1\u5668&#xff0c;\u5982\u901a\u8fc7hyper\u5e93\u5206\u53d1HTTP\u8bf7\u6c42\u3002<\/p>\n<p>use hyper::{Body, Request, Response, Server};<br \/>\nuse hyper::service::{make_service_fn, service_fn};<\/p>\n<p>async fn handle(req: Request&lt;Body&gt;) -&gt; Result&lt;Response&lt;Body&gt;, hyper::Error&gt; {<br \/>\n    Ok(Response::new(Body::from(&#034;Proxied Response&#034;)))<br \/>\n}<\/p>\n<h4>\u65e5\u5fd7\u6536\u96c6\u670d\u52a1<\/h4>\n<p>\u6784\u5efa\u96c6\u4e2d\u5f0f\u65e5\u5fd7\u670d\u52a1\u5668&#xff0c;\u5982\u4f7f\u7528flume\u63a5\u6536\u5e76\u5904\u7406\u65e5\u5fd7\u6d41\u3002<\/p>\n<p>use flume::{Receiver, Sender};<br \/>\nlet (tx, rx): (Sender&lt;String&gt;, Receiver&lt;String&gt;) &#061; flume::unbounded();<br \/>\nstd::thread::spawn(move || {<br \/>\n    while let Ok(log) &#061; rx.recv() {<br \/>\n        println!(&#034;[LOG] {}&#034;, log);<br \/>\n    }<br \/>\n});<\/p>\n<h4>\u90ae\u4ef6\u670d\u52a1\u5668<\/h4>\n<p>\u5f00\u53d1SMTP\u670d\u52a1\u7aef&#xff0c;\u5982\u901a\u8fc7lettre\u5e93\u5904\u7406\u90ae\u4ef6\u6536\u53d1\u3002<\/p>\n<p>use lettre::transport::smtp::SmtpTransport;<br \/>\nuse lettre::{Message, Transport};<\/p>\n<p>let email &#061; Message::builder()<br \/>\n    .from(&#034;sender&#064;example.com&#034;.parse().unwrap())<br \/>\n    .to(&#034;receiver&#064;example.com&#034;.parse().unwrap())<br \/>\n    .subject(&#034;Rust SMTP Test&#034;)<br \/>\n    .body(&#034;Hello from Rust!&#034;.to_string())<br \/>\n    .unwrap();<\/p>\n<p>let mailer &#061; SmtpTransport::unencrypted_localhost();<br \/>\nmailer.send(&amp;email).unwrap();<\/p>\n<h4>\u89c6\u9891\u6d41\u670d\u52a1\u5668<\/h4>\n<p>\u901a\u8fc7tokio-rtmp\u5b9e\u73b0\u5b9e\u65f6\u89c6\u9891\u6d41\u5206\u53d1\u670d\u52a1\u5668\u3002<\/p>\n<p>use tokio_rtmp::server::Server;<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let server &#061; Server::bind(&#034;0.0.0.0:1935&#034;).await.unwrap();<br \/>\n    server.run().await.unwrap();<br \/>\n}<\/p>\n<h4>DNS\u670d\u52a1\u5668<\/h4>\n<p>\u6784\u5efa\u81ea\u5b9a\u4e49DNS\u89e3\u6790\u670d\u52a1&#xff0c;\u5982\u4f7f\u7528trust-dns-server\u5e93\u3002<\/p>\n<p>use trust_dns_server::authority::Catalog;<br \/>\nuse trust_dns_server::server::ServerFuture;<\/p>\n<p>let catalog &#061; Catalog::new();<br \/>\nlet mut server &#061; ServerFuture::new(catalog);<br \/>\nserver.register_listener(listener, Duration::from_secs(2)).await.unwrap();<\/p>\n<h4>\u7f13\u5b58\u670d\u52a1\u5668<\/h4>\n<p>\u5f00\u53d1Memcached\u517c\u5bb9\u670d\u52a1\u5668&#xff0c;\u5982\u4f7f\u7528mio\u5904\u7406\u9ad8\u901f\u952e\u503c\u5b58\u50a8\u3002<\/p>\n<p>use mio::net::TcpListener;<br \/>\nuse std::collections::HashMap;<\/p>\n<p>let mut cache &#061; HashMap::new();<br \/>\nlet listener &#061; TcpListener::bind(&#034;127.0.0.1:11211&#034;.parse().unwrap()).unwrap();<\/p>\n<h4>\u76d1\u63a7\u4ee3\u7406<\/h4>\n<p>\u5b9e\u73b0Prometheus\u6307\u6807\u6536\u96c6\u670d\u52a1&#xff0c;\u4f7f\u7528prometheus\u5e93\u66b4\u9732metrics\u3002<\/p>\n<p>use prometheus::{Encoder, TextEncoder};<\/p>\n<p>let metric_family &#061; prometheus::gather();<br \/>\nlet mut buffer &#061; vec![];<br \/>\nlet encoder &#061; TextEncoder::new();<br \/>\nencoder.encode(&amp;metric_family, &amp;mut buffer).unwrap();<\/p>\n<h4>\u6d88\u606f\u961f\u5217<\/h4>\n<p>\u6784\u5efaAMQP\/RabbitMQ\u66ff\u4ee3\u670d\u52a1&#xff0c;\u5982\u57fa\u4e8elapin\u5b9e\u73b0\u6d88\u606f\u961f\u5217\u6838\u5fc3\u3002<\/p>\n<p>use lapin::{Connection, ConnectionProperties};<\/p>\n<p>#[tokio::main]<br \/>\nasync fn main() {<br \/>\n    let conn &#061; Connection::connect(<br \/>\n        &#034;amqp:\/\/guest:guest&#064;localhost:5672&#034;,<br \/>\n        ConnectionProperties::default(),<br \/>\n    ).await.unwrap();<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">API\u7f51\u5173<\/h4>\n<p>\u5f00\u53d1\u7edf\u4e00\u5165\u53e3\u7f51\u5173&#xff0c;\u5982\u901a\u8fc7axum\u5b9e\u73b0\u8def\u7531\u548c\u9274\u6743\u6574\u5408\u3002<\/p>\n<p>use axum::{Router, routing::get};<\/p>\n<p>async fn handler() -&gt; &amp;&#039;static str { &#034;Gateway Response&#034; }<\/p>\n<p>let app &#061; Router::new().route(&#034;\/&#034;, get(handler));<br \/>\naxum::Server::bind(&amp;&#034;0.0.0.0:3000&#034;.parse().unwrap())<br \/>\n    .serve(app.into_make_service())<br \/>\n    .await<br \/>\n    .unwrap();<\/p>\n<h4>\u8eab\u4efd\u9a8c\u8bc1\u670d\u52a1<\/h4>\n<p>\u5b9e\u73b0OAuth2.0\u670d\u52a1\u5668&#xff0c;\u5982\u4f7f\u7528oxide-auth\u5e93\u5904\u7406\u4ee4\u724c\u9881\u53d1\u3002<\/p>\n<p>use oxide_auth::endpoint::Endpoint;<br \/>\nuse oxide_auth::frontends::simple::endpoint::Generic;<\/p>\n<p>let mut endpoint &#061; Generic::new(());<br \/>\nlet response &#061; endpoint.authorization(&amp;mut request).unwrap();<\/p>\n<h4>\u914d\u7f6e\u4e2d\u5fc3<\/h4>\n<p>\u5f00\u53d1\u5206\u5e03\u5f0f\u914d\u7f6e\u7ba1\u7406\u670d\u52a1\u5668&#xff0c;\u5982\u901a\u8fc7serde\u548cconfig\u5e93\u52a8\u6001\u52a0\u8f7d\u914d\u7f6e\u3002<\/p>\n<p>use config::{Config, File};<br \/>\nlet mut settings &#061; Config::default();<br \/>\nsettings.merge(File::with_name(&#034;config&#034;)).unwrap();<\/p>\n<h4 style=\"background-color:transparent\">\u65f6\u95f4\u5e8f\u5217\u6570\u636e\u5e93<\/h4>\n<p>\u6784\u5efaTSDB\u67e5\u8be2\u5f15\u64ce&#xff0c;\u5982\u4f7f\u7528arrow\u548cparquet\u5904\u7406\u65f6\u5e8f\u6570\u636e\u3002<\/p>\n<p>use arrow::array::{Float64Array, TimestampNanosecondArray};<br \/>\nuse arrow::record_batch::RecordBatch;<\/p>\n<p>let timestamps &#061; TimestampNanosecondArray::from(vec![1, 2, 3]);<br \/>\nlet values &#061; Float64Array::from(vec![10.5, 11.3, 9.8]);<br \/>\nRecordBatch::try_new(<br \/>\n    schema,<br \/>\n    vec![Arc::new(timestamps), Arc::new(values)],<br \/>\n).unwrap();<\/p>\n<h4 style=\"background-color:transparent\">\u7528\u6237\u7ba1\u7406\u6a21\u5757<\/h4>\n<h5>\u7528\u6237\u767b\u5f55\u63a5\u53e3&#xff08;JWT \u8ba4\u8bc1&#xff09;<\/h5>\n<p>#[post(&#034;\/login&#034;)]<br \/>\nasync fn login(user: web::Json&lt;UserLogin&gt;) -&gt; impl Responder {<br \/>\n    let token &#061; generate_jwt(&amp;user.username);<br \/>\n    HttpResponse::Ok().json(LoginResponse { token })<br \/>\n}<\/p>\n<h5>\u7528\u6237\u6ce8\u518c\u63a5\u53e3&#xff08;\u5bc6\u7801\u52a0\u5bc6&#xff09;<\/h5>\n<p>#[post(&#034;\/register&#034;)]<br \/>\nasync fn register(user: web::Json&lt;UserRegister&gt;) -&gt; impl Responder {<br \/>\n    let hashed &#061; bcrypt::hash(user.password, 10)?;<br \/>\n    let new_user &#061; User {<br \/>\n        username: user.username,<br \/>\n        password: hashed<br \/>\n    };<br \/>\n    HttpResponse::Created().json(new_user)<br \/>\n}<\/p>\n<h5>\u7528\u6237\u4fe1\u606f\u4fee\u6539&#xff08;\u6743\u9650\u9a8c\u8bc1&#xff09;<\/h5>\n<p>#[put(&#034;\/users\/{id}&#034;)]<br \/>\nasync fn update_user(<br \/>\n    id: web::Path&lt;i32&gt;,<br \/>\n    user: web::Json&lt;UserUpdate&gt;,<br \/>\n    req: HttpRequest<br \/>\n) -&gt; impl Responder {<br \/>\n    validate_admin(req)?;<br \/>\n    HttpResponse::Ok().json(format!(&#034;Updated user {}&#034;, id))<br \/>\n}<\/p>\n<h4>\u6570\u636e\u67e5\u8be2\u6a21\u5757<\/h4>\n<h5>\u5206\u9875\u67e5\u8be2\u63a5\u53e3<\/h5>\n<p>#[get(&#034;\/data&#034;)]<br \/>\nasync fn list_data(query: web::Query&lt;Pagination&gt;) -&gt; impl Responder {<br \/>\n    let items &#061; fetch_data(query.page, query.size).await?;<br \/>\n    HttpResponse::Ok().json(items)<br \/>\n}<\/p>\n<h5>\u6761\u4ef6\u7b5b\u9009\u63a5\u53e3<\/h5>\n<p>#[get(&#034;\/data\/filter&#034;)]<br \/>\nasync fn filter_data(params: web::Query&lt;FilterParams&gt;) -&gt; impl Responder {<br \/>\n    let results &#061; apply_filters(params).await?;<br \/>\n    HttpResponse::Ok().json(results)<br \/>\n}<\/p>\n<h5 style=\"background-color:transparent\">\u6570\u636e\u805a\u5408\u7edf\u8ba1<\/h5>\n<p>#[get(&#034;\/stats&#034;)]<br \/>\nasync fn data_stats() -&gt; impl Responder {<br \/>\n    let stats &#061; calculate_stats().await?;<br \/>\n    HttpResponse::Ok().json(stats)<br \/>\n}<\/p>\n<h4>\u6587\u4ef6\u64cd\u4f5c\u6a21\u5757<\/h4>\n<h5>\u6587\u4ef6\u4e0a\u4f20\u63a5\u53e3<\/h5>\n<p>#[post(&#034;\/upload&#034;)]<br \/>\nasync fn upload_file(mut payload: web::Payload) -&gt; impl Responder {<br \/>\n    let filepath &#061; save_uploaded_file(&amp;mut payload).await?;<br \/>\n    HttpResponse::Ok().json(filepath)<br \/>\n}<\/p>\n<h5>\u6587\u4ef6\u4e0b\u8f7d\u63a5\u53e3<\/h5>\n<p>#[get(&#034;\/download\/{filename}&#034;)]<br \/>\nasync fn download_file(filename: web::Path&lt;String&gt;) -&gt; impl Responder {<br \/>\n    let file &#061; File::open(format!(&#034;.\/files\/{}&#034;, filename))?;<br \/>\n    HttpResponse::Ok().streaming(file)<br \/>\n}<\/p>\n<h4>\u7cfb\u7edf\u76d1\u63a7\u6a21\u5757<\/h4>\n<h5>\u5065\u5eb7\u68c0\u67e5\u63a5\u53e3<\/h5>\n<p>#[get(&#034;\/health&#034;)]<br \/>\nasync fn health_check() -&gt; impl Responder {<br \/>\n    HttpResponse::Ok().json(&#034;OK&#034;)<br \/>\n}<\/p>\n<h5><\/h5>\n<h5>\u6027\u80fd\u6307\u6807\u63a5\u53e3<\/h5>\n<p>#[get(&#034;\/metrics&#034;)]<br \/>\nasync fn system_metrics() -&gt; impl Responder {<br \/>\n    let metrics &#061; collect_metrics();<br \/>\n    HttpResponse::Ok().json(metrics)<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u5b8c\u6574\u9879\u76ee\u7ed3\u6784\u793a\u4f8b<\/h4>\n<p>\u5178\u578b Actix-web \u5e94\u7528\u7ed3\u6784&#xff1a;<\/p>\n<p>src\/<br \/>\n\u251c\u2500\u2500 main.rs         # \u670d\u52a1\u5668\u542f\u52a8<br \/>\n\u251c\u2500\u2500 routes\/         # \u8def\u7531\u6a21\u5757<br \/>\n\u251c\u2500\u2500 handlers\/       # \u4e1a\u52a1\u903b\u8f91<br \/>\n\u251c\u2500\u2500 models\/         # \u6570\u636e\u7ed3\u6784<br \/>\n\u251c\u2500\u2500 middleware\/     # \u4e2d\u95f4\u4ef6<br \/>\n\u2514\u2500\u2500 database\/       # \u6570\u636e\u5e93\u8fde\u63a5<\/p>\n<p>\u6570\u636e\u5e93\u8fde\u63a5\u6c60\u914d\u7f6e\u793a\u4f8b&#xff1a;<\/p>\n<p>pub fn configure_db(cfg: &amp;mut web::ServiceConfig) {<br \/>\n    let pool &#061; PgPool::connect(&#034;postgres:\/\/user:pass&#064;localhost\/db&#034;);<br \/>\n    cfg.data(pool);<br \/>\n}<\/p>\n<p>JWT \u4e2d\u95f4\u4ef6\u793a\u4f8b&#xff1a;<\/p>\n<p>pub struct JwtMiddleware;<\/p>\n<p>impl&lt;S&gt; Transform&lt;S, ServiceRequest&gt; for JwtMiddleware {<br \/>\n    type Response &#061; ServiceResponse;<br \/>\n    type Error &#061; Error;<br \/>\n    type Transform &#061; JwtMiddlewareService&lt;S&gt;;<br \/>\n    type InitError &#061; ();<br \/>\n    type Future &#061; Ready&lt;Result&lt;Self::Transform, Self::InitError&gt;&gt;;<\/p>\n<p>    fn new_transform(&amp;self, service: S) -&gt; Self::Future {<br \/>\n        ready(Ok(JwtMiddlewareService { service }))<br \/>\n    }<br \/>\n}<\/p>\n<p>\u4ee5\u4e0a\u793a\u4f8b\u5c55\u793a\u4e86 MIS \u7cfb\u7edf\u7684\u6838\u5fc3\u63a5\u53e3\u5b9e\u73b0\u6a21\u5f0f\u3002\u5b9e\u9645\u5f00\u53d1\u4e2d\u9700\u8981\u7ed3\u5408\u5177\u4f53\u4e1a\u52a1\u9700\u6c42\u6269\u5c55\u4ee5\u4e0b\u65b9\u9762&#xff1a;<\/p>\n<ul>\n<li>RBAC \u6743\u9650\u63a7\u5236\u7cfb\u7edf<\/li>\n<li>\u6570\u636e\u9a8c\u8bc1\u5c42<\/li>\n<li>\u5ba1\u8ba1\u65e5\u5fd7\u8bb0\u5f55<\/li>\n<li>\u7f13\u5b58\u673a\u5236<\/li>\n<li>\u6d88\u606f\u961f\u5217\u96c6\u6210<\/li>\n<li>\u5206\u5e03\u5f0f\u9501\u5b9e\u73b0<\/li>\n<li>\u81ea\u52a8\u5316\u6d4b\u8bd5\u6a21\u5757<\/li>\n<\/ul>\n<p>\u5b8c\u6574\u9879\u76ee\u5efa\u8bae\u91c7\u7528\u5206\u5c42\u67b6\u6784\u8bbe\u8ba1&#xff0c;\u901a\u8fc7 actix-web::Scope \u7ec4\u7ec7\u8def\u7531\u5206\u7ec4&#xff0c;\u4f7f\u7528 derive_more \u5e93\u7b80\u5316\u9519\u8bef\u5904\u7406&#xff0c;\u96c6\u6210 sqlx \u6216 diesel \u8fdb\u884c\u6570\u636e\u5e93\u64cd\u4f5c\u3002<\/p>\n<h3>\u57fa\u4e8eRust\u7f16\u5199\u624b\u673a\u756a\u8304\u8bfb\u4e66<\/h3>\n<p>\u4ee5\u4e0b\u662f\u57fa\u4e8eRust\u7f16\u5199\u624b\u673a\u756a\u8304\u8bfb\u4e66\u5e94\u7528\u768420\u4e2a\u5b9e\u4f8b\u4ee3\u7801\u7247\u6bb5&#xff0c;\u6db5\u76d6\u6838\u5fc3\u529f\u80fd\u5b9e\u73b0&#xff1a;<\/p>\n<h4 style=\"background-color:transparent\">\u57fa\u7840\u7ed3\u6784<\/h4>\n<p>\/\/ \u5b9e\u4f8b1&#xff1a;\u5b9a\u4e49\u756a\u8304\u949f\u72b6\u6001\u679a\u4e3e<br \/>\nenum PomodoroState {<br \/>\n    Focus,<br \/>\n    ShortBreak,<br \/>\n    LongBreak,<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b2&#xff1a;\u8bfb\u4e66\u4efb\u52a1\u7ed3\u6784\u4f53<br \/>\nstruct ReadingTask {<br \/>\n    title: String,<br \/>\n    pages: u32,<br \/>\n    completed: bool,<br \/>\n    current_page: u32,<br \/>\n}<\/p>\n<h4>\u8ba1\u65f6\u529f\u80fd<\/h4>\n<p>\/\/ \u5b9e\u4f8b3&#xff1a;\u5012\u8ba1\u65f6\u5b9e\u73b0<br \/>\nuse std::time::Duration;<br \/>\nuse std::thread;<\/p>\n<p>fn countdown(seconds: u64) {<br \/>\n    for i in (1..&#061;seconds).rev() {<br \/>\n        println!(&#034;Remaining: {}s&#034;, i);<br \/>\n        thread::sleep(Duration::from_secs(1));<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b4&#xff1a;\u8ba1\u65f6\u5668\u7ed3\u6784\u4f53<br \/>\nstruct Timer {<br \/>\n    duration: Duration,<br \/>\n    remaining: Duration,<br \/>\n    is_running: bool,<br \/>\n}<\/p>\n<h4>\u7528\u6237\u754c\u9762<\/h4>\n<p>\/\/ \u5b9e\u4f8b5&#xff1a;\u7ec8\u7aefUI\u6e32\u67d3<br \/>\nuse tui::{<br \/>\n    Terminal,<br \/>\n    backend::Backend,<br \/>\n    layout::{Layout, Direction, Constraint},<br \/>\n    widgets::{Block, Borders, Paragraph},<br \/>\n};<\/p>\n<p>fn render_ui&lt;B: Backend&gt;(terminal: &amp;mut Terminal&lt;B&gt;) {<br \/>\n    terminal.draw(|f| {<br \/>\n        let chunks &#061; Layout::default()<br \/>\n            .direction(Direction::Vertical)<br \/>\n            .constraints([Constraint::Percentage(100)].as_ref())<br \/>\n            .split(f.size());<\/p>\n<p>        let block &#061; Block::default()<br \/>\n            .title(&#034;\u756a\u8304\u8bfb\u4e66&#034;)<br \/>\n            .borders(Borders::ALL);<br \/>\n        f.render_widget(block, chunks[0]);<br \/>\n    }).unwrap();<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b6&#xff1a;\u79fb\u52a8\u7aef\u6309\u94ae\u7ec4\u4ef6<br \/>\nstruct MobileButton {<br \/>\n    text: String,<br \/>\n    position: (u32, u32),<br \/>\n    size: (u32, u32),<br \/>\n    callback: Box&lt;dyn Fn()&gt;,<br \/>\n}<\/p>\n<h4>\u6570\u636e\u6301\u4e45\u5316<\/h4>\n<p>\/\/ \u5b9e\u4f8b7&#xff1a;JSON\u4efb\u52a1\u5b58\u50a8<br \/>\nuse serde::{Serialize, Deserialize};<br \/>\nuse std::fs;<\/p>\n<p>#[derive(Serialize, Deserialize)]<br \/>\nstruct TaskList {<br \/>\n    tasks: Vec&lt;ReadingTask&gt;,<br \/>\n}<\/p>\n<p>fn save_tasks(tasks: &amp;TaskList, path: &amp;str) -&gt; std::io::Result&lt;()&gt; {<br \/>\n    let json &#061; serde_json::to_string(tasks)?;<br \/>\n    fs::write(path, json)<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b8&#xff1a;SQLite\u6570\u636e\u5e93\u64cd\u4f5c<br \/>\nuse rusqlite::{Connection, Result};<\/p>\n<p>fn init_db() -&gt; Result&lt;Connection&gt; {<br \/>\n    let conn &#061; Connection::open(&#034;reading.db&#034;)?;<br \/>\n    conn.execute(<br \/>\n        &#034;CREATE TABLE IF NOT EXISTS tasks (<br \/>\n            id INTEGER PRIMARY KEY,<br \/>\n            title TEXT NOT NULL,<br \/>\n            pages INTEGER NOT NULL<br \/>\n        )&#034;,<br \/>\n        [],<br \/>\n    )?;<br \/>\n    Ok(conn)<br \/>\n}<\/p>\n<h4>\u901a\u77e5\u7cfb\u7edf<\/h4>\n<p>\/\/ \u5b9e\u4f8b9&#xff1a;\u7cfb\u7edf\u901a\u77e5<br \/>\n#[cfg(target_os &#061; &#034;android&#034;)]<br \/>\nuse jni::{JNIEnv, objects::JObject};<\/p>\n<p>fn send_notification(title: &amp;str, message: &amp;str) {<br \/>\n    #[cfg(target_os &#061; &#034;android&#034;)]<br \/>\n    {<br \/>\n        let env &#061; JNIEnv::from_thread();<br \/>\n        let context &#061; JObject::null();<br \/>\n        \/\/ \u5b9e\u9645\u8c03\u7528Android\u901a\u77e5API<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b10&#xff1a;\u632f\u52a8\u53cd\u9988<br \/>\n#[cfg(target_os &#061; &#034;android&#034;)]<br \/>\nfn vibrate(duration_ms: i64) {<br \/>\n    \/\/ \u8c03\u7528Android\u632f\u52a8API<br \/>\n}<\/p>\n<h4>\u7edf\u8ba1\u529f\u80fd<\/h4>\n<p>\/\/ \u5b9e\u4f8b11&#xff1a;\u9605\u8bfb\u8fdb\u5ea6\u8ba1\u7b97<br \/>\nimpl ReadingTask {<br \/>\n    fn progress(&amp;self) -&gt; f32 {<br \/>\n        if self.pages &#061;&#061; 0 {<br \/>\n            0.0<br \/>\n        } else {<br \/>\n            self.current_page as f32 \/ self.pages as f32 * 100.0<br \/>\n        }<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b12&#xff1a;\u5468\u7edf\u8ba1\u7ed3\u6784<br \/>\nstruct WeeklyStats {<br \/>\n    focus_sessions: u32,<br \/>\n    pages_read: u32,<br \/>\n    completion_rate: f32,<br \/>\n}<\/p>\n<h4>\u7f51\u7edc\u540c\u6b65<\/h4>\n<p>\/\/ \u5b9e\u4f8b13&#xff1a;API\u5ba2\u6237\u7aef<br \/>\nuse reqwest::Client;<\/p>\n<p>async fn sync_tasks(api_url: &amp;str, tasks: &amp;TaskList) -&gt; Result&lt;(), reqwest::Error&gt; {<br \/>\n    let client &#061; Client::new();<br \/>\n    client.post(api_url)<br \/>\n        .json(tasks)<br \/>\n        .send()<br \/>\n        .await?;<br \/>\n    Ok(())<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b14&#xff1a;WebSocket\u76d1\u542c<br \/>\nuse tokio_tungstenite::connect_async;<\/p>\n<p>async fn connect_to_server(url: &amp;str) {<br \/>\n    let (ws_stream, _) &#061; connect_async(url).await.unwrap();<br \/>\n    \/\/ \u5904\u7406\u6d88\u606f<br \/>\n}<\/p>\n<h4 style=\"background-color:transparent\">\u6d4b\u8bd5\u6a21\u5757<\/h4>\n<p>\/\/ \u5b9e\u4f8b15&#xff1a;\u5355\u5143\u6d4b\u8bd5<br \/>\n#[cfg(test)]<br \/>\nmod tests {<br \/>\n    use super::*;<\/p>\n<p>    #[test]<br \/>\n    fn test_progress_calculation() {<br \/>\n        let task &#061; ReadingTask {<br \/>\n            current_page: 50,<br \/>\n            pages: 100,<br \/>\n            ..Default::default()<br \/>\n        };<br \/>\n        assert_eq!(task.progress(), 50.0);<br \/>\n    }<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b16&#xff1a;\u96c6\u6210\u6d4b\u8bd5<br \/>\n#[cfg(test)]<br \/>\nmod integration_tests {<br \/>\n    #[test]<br \/>\n    fn test_db_operations() {<br \/>\n        let conn &#061; init_db().unwrap();<br \/>\n        \/\/ \u6d4b\u8bd5\u6570\u636e\u5e93\u64cd\u4f5c<br \/>\n    }<br \/>\n}<\/p>\n<h4>\u8de8\u5e73\u53f0\u652f\u6301<\/h4>\n<p>\/\/ \u5b9e\u4f8b17&#xff1a;\u6761\u4ef6\u7f16\u8bd1<br \/>\n#[cfg(target_os &#061; &#034;android&#034;)]<br \/>\nfn platform_specific() {<br \/>\n    \/\/ Android\u7279\u5b9a\u4ee3\u7801<br \/>\n}<\/p>\n<p>#[cfg(target_os &#061; &#034;ios&#034;)]<br \/>\nfn platform_specific() {<br \/>\n    \/\/ iOS\u7279\u5b9a\u4ee3\u7801<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b18&#xff1a;FFI\u7ed1\u5b9a<br \/>\n#[no_mangle]<br \/>\npub extern &#034;C&#034; fn start_timer(duration: u32) {<br \/>\n    \/\/ \u4f9b\u539f\u751f\u5e73\u53f0\u8c03\u7528\u7684\u63a5\u53e3<br \/>\n}<\/p>\n<h4>\u9ad8\u7ea7\u529f\u80fd<\/h4>\n<p>\/\/ \u5b9e\u4f8b19&#xff1a;\u6587\u672c\u5206\u6790<br \/>\nuse rayon::prelude::*;<\/p>\n<p>fn analyze_text(text: &amp;str) -&gt; HashMap&lt;String, u32&gt; {<br \/>\n    text.par_split_whitespace()<br \/>\n        .fold(HashMap::new, |mut acc, word| {<br \/>\n            *acc.entry(word.to_lowercase()).or_default() &#043;&#061; 1;<br \/>\n            acc<br \/>\n        })<br \/>\n        .reduce(HashMap::new, |mut a, b| {<br \/>\n            for (k, v) in b {<br \/>\n                *a.entry(k).or_default() &#043;&#061; v;<br \/>\n            }<br \/>\n            a<br \/>\n        })<br \/>\n}<\/p>\n<p>\/\/ \u5b9e\u4f8b20&#xff1a;\u673a\u5668\u5b66\u4e60\u96c6\u6210<br \/>\nuse tract_onnx::prelude::*;<\/p>\n<p>fn predict_reading_time(model_path: &amp;str, input: &amp;[f32]) -&gt; Result&lt;f32&gt; {<br \/>\n    let model &#061; tract_onnx::onnx().model_for_path(model_path)?;<br \/>\n    let plan &#061; SimplePlan::new(model)?;<br \/>\n    let result &#061; plan.run(tensor1(input))?;<br \/>\n    Ok(result[0].to_scalar::&lt;f32&gt;()?)<br \/>\n}<\/p>\n<p>\u8fd9\u4e9b\u5b9e\u4f8b\u6db5\u76d6\u4e86\u4ece\u57fa\u7840\u7ed3\u6784\u5230\u9ad8\u7ea7\u529f\u80fd\u7684\u5404\u4e2a\u65b9\u9762&#xff0c;\u53ef\u6839\u636e\u5b9e\u9645\u9700\u6c42\u8fdb\u884c\u7ec4\u5408\u548c\u6269\u5c55\u3002\u5bf9\u4e8e\u79fb\u52a8\u7aef\u5f00\u53d1&#xff0c;\u5efa\u8bae\u7ed3\u5408rust-android\u6216rust-ios\u5de5\u5177\u94fe\u8fdb\u884c\u539f\u751f\u5e73\u53f0\u96c6\u6210\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6587\u7ae0\u6d4f\u89c8\u9605\u8bfb832\u6b21\uff0c\u70b9\u8d5e26\u6b21\uff0c\u6536\u85cf12\u6b21\u3002\u8fd9\u7bc7\u6280\u672f\u6587\u7ae0\u6458\u8981\u6db5\u76d6\u4e86\u591a\u4e2aRust\u5f00\u53d1\u573a\u666f\u7684\u5b9e\u7528\u4ee3\u7801\u793a\u4f8b\uff0c\u4e3b\u8981\u5305\u62ec\uff1a \u5b57\u8282\u8df3\u52a8\u7ea7\u670d\u52a1\u5668\u5f00\u53d1 \u7f51\u7edc\u901a\u4fe1\uff08\u5f02\u6b65TCP\/HTTP\u670d\u52a1\u5668\uff09 \u9ad8\u5e76\u53d1\u5904\u7406\uff08\u65e0\u9501\u961f\u5217\/\u5f02\u6b65\u4efb\u52a1\u6c60\uff09 \u6570\u636e\u5b58\u50a8\uff08Redis\/\u6570\u636e\u5e93\u64cd\u4f5c\uff09 \u6027\u80fd\u4f18\u5316\uff08SIMD\/\u5185\u5b58\u6c60\uff09 \u4e91\u539f\u751f\u6846\u67b6Volo\u5b9e\u8df5 HTTP\/gRPC\u670d\u52a1\u642d\u5efa Kubernetes\u5065\u5eb7\u68c0\u67e5 \u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6 \u5206\u5e03\u5f0f\u8ffd\u8e2a\u7b49\u4e91\u539f\u751f\u529f\u80fd Tokio\u5f02\u6b65\u8fd0\u884c\u65f6\u5e94\u7528 \u57fa\u7840\u5f02\u6b65\u4efb\u52a1 TCP\u670d\u52a1\u5668\/\u5ba2\u6237\u7aef \u5b9a\u65f6\u5668\/\u6587\u4ef6I\/O WebSocket\u901a\u4fe1\u7b49 \u5176\u4ed6\u5e94\u7528\u573a\u666f \u6570\u636e\u5e93CRUD\u64cd\u4f5c Web\u5f00\u53d1\u6846\u67b6 _rust\u9ad8\u5e76\u53d1<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[206,190,43],"topic":[],"class_list":["post-46030","post","type-post","status-publish","format-standard","hentry","category-server","tag-rust","tag-190","tag-43"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/46030.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u6587\u7ae0\u6d4f\u89c8\u9605\u8bfb832\u6b21\uff0c\u70b9\u8d5e26\u6b21\uff0c\u6536\u85cf12\u6b21\u3002\u8fd9\u7bc7\u6280\u672f\u6587\u7ae0\u6458\u8981\u6db5\u76d6\u4e86\u591a\u4e2aRust\u5f00\u53d1\u573a\u666f\u7684\u5b9e\u7528\u4ee3\u7801\u793a\u4f8b\uff0c\u4e3b\u8981\u5305\u62ec\uff1a \u5b57\u8282\u8df3\u52a8\u7ea7\u670d\u52a1\u5668\u5f00\u53d1 \u7f51\u7edc\u901a\u4fe1\uff08\u5f02\u6b65TCP\/HTTP\u670d\u52a1\u5668\uff09 \u9ad8\u5e76\u53d1\u5904\u7406\uff08\u65e0\u9501\u961f\u5217\/\u5f02\u6b65\u4efb\u52a1\u6c60\uff09 \u6570\u636e\u5b58\u50a8\uff08Redis\/\u6570\u636e\u5e93\u64cd\u4f5c\uff09 \u6027\u80fd\u4f18\u5316\uff08SIMD\/\u5185\u5b58\u6c60\uff09 \u4e91\u539f\u751f\u6846\u67b6Volo\u5b9e\u8df5 HTTP\/gRPC\u670d\u52a1\u642d\u5efa Kubernetes\u5065\u5eb7\u68c0\u67e5 \u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6 \u5206\u5e03\u5f0f\u8ffd\u8e2a\u7b49\u4e91\u539f\u751f\u529f\u80fd Tokio\u5f02\u6b65\u8fd0\u884c\u65f6\u5e94\u7528 \u57fa\u7840\u5f02\u6b65\u4efb\u52a1 TCP\u670d\u52a1\u5668\/\u5ba2\u6237\u7aef \u5b9a\u65f6\u5668\/\u6587\u4ef6I\/O WebSocket\u901a\u4fe1\u7b49 \u5176\u4ed6\u5e94\u7528\u573a\u666f \u6570\u636e\u5e93CRUD\u64cd\u4f5c Web\u5f00\u53d1\u6846\u67b6 _rust\u9ad8\u5e76\u53d1\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/46030.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2025-07-29T18:13:02+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"30 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/46030.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/46030.html\",\"name\":\"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2025-07-29T18:13:02+00:00\",\"dateModified\":\"2025-07-29T18:13:02+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/46030.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/46030.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/46030.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/46030.html","og_locale":"zh_CN","og_type":"article","og_title":"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u6587\u7ae0\u6d4f\u89c8\u9605\u8bfb832\u6b21\uff0c\u70b9\u8d5e26\u6b21\uff0c\u6536\u85cf12\u6b21\u3002\u8fd9\u7bc7\u6280\u672f\u6587\u7ae0\u6458\u8981\u6db5\u76d6\u4e86\u591a\u4e2aRust\u5f00\u53d1\u573a\u666f\u7684\u5b9e\u7528\u4ee3\u7801\u793a\u4f8b\uff0c\u4e3b\u8981\u5305\u62ec\uff1a \u5b57\u8282\u8df3\u52a8\u7ea7\u670d\u52a1\u5668\u5f00\u53d1 \u7f51\u7edc\u901a\u4fe1\uff08\u5f02\u6b65TCP\/HTTP\u670d\u52a1\u5668\uff09 \u9ad8\u5e76\u53d1\u5904\u7406\uff08\u65e0\u9501\u961f\u5217\/\u5f02\u6b65\u4efb\u52a1\u6c60\uff09 \u6570\u636e\u5b58\u50a8\uff08Redis\/\u6570\u636e\u5e93\u64cd\u4f5c\uff09 \u6027\u80fd\u4f18\u5316\uff08SIMD\/\u5185\u5b58\u6c60\uff09 \u4e91\u539f\u751f\u6846\u67b6Volo\u5b9e\u8df5 HTTP\/gRPC\u670d\u52a1\u642d\u5efa Kubernetes\u5065\u5eb7\u68c0\u67e5 \u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6 \u5206\u5e03\u5f0f\u8ffd\u8e2a\u7b49\u4e91\u539f\u751f\u529f\u80fd Tokio\u5f02\u6b65\u8fd0\u884c\u65f6\u5e94\u7528 \u57fa\u7840\u5f02\u6b65\u4efb\u52a1 TCP\u670d\u52a1\u5668\/\u5ba2\u6237\u7aef \u5b9a\u65f6\u5668\/\u6587\u4ef6I\/O WebSocket\u901a\u4fe1\u7b49 \u5176\u4ed6\u5e94\u7528\u573a\u666f \u6570\u636e\u5e93CRUD\u64cd\u4f5c Web\u5f00\u53d1\u6846\u67b6 _rust\u9ad8\u5e76\u53d1","og_url":"https:\/\/www.wsisp.com\/helps\/46030.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2025-07-29T18:13:02+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"30 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/46030.html","url":"https:\/\/www.wsisp.com\/helps\/46030.html","name":"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2025-07-29T18:13:02+00:00","dateModified":"2025-07-29T18:13:02+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/46030.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/46030.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/46030.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"Rust\u5f81\u670d\u5b57\u8282\u8df3\u52a8\uff1a\u9ad8\u5e76\u53d1\u670d\u52a1\u5668\u5b9e\u6218"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/46030","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=46030"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/46030\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=46030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=46030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=46030"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=46030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}