rust 新手,只会 python 和 c
use actix_web::{get, web, App, HttpServer, Responder};
#[get("/hello/{name}")]
async fn greet(name: web::Path<String>) -> impl Responder {
format!("Hello {name}!")
}
#[actix_web::main] // or #[tokio::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/hello", web::get().to(|| async { "Hello World!" }))
.service(greet)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
这里的 main 函数为什么需要一个返回值 std::io::Result<()>
呢?
按照写 c语言的经验,main 函数一般返回一个 int,表示程序退出状态码
而 rust 这里面,需要一个 std::io::Result<()>
就不能理解,这玩意都不是一个整数
删掉 main 函数的 std::io::Result<()>
还会报错
╰─➤ cargo run 130 ↵
Compiling wmm v0.1.0 (/Users/ponponon/Desktop/code/me/wmm)
error[E0308]: mismatched types
--> src/main.rs:8:1
|
8 | #[actix_web::main] // or #[tokio::main]
| -^^^^^^^^^^^^^^^^^
| |
| expected `()`, found enum `Result`
| expected `()` because of default return type
|
= note: expected unit type `()`
found enum `Result<(), std::io::Error>`
= note: this error originates in the attribute macro `::actix_web::rt::main` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0308`.
error: could not compile `wmm` due to previous error
比如下面的例子,main 函数是没有返回值
fn greet_world() {
let southern_germany = "Grüß Gott!";
let chinese = "世界,你好";
let english = "World, hello";
let regions = [southern_germany, chinese, english];
for region in regions.iter() {
println!("{}", ®ion);
}
}
fn main() {
greet_world();
}
为什么 actix_web 需要返回值呢?
难道和 #[actix_web::main]
有关系吗?
但是我直接这样,也是可以跑的
#[actix_web::main]
async fn main() {
async { println!("Hello world"); }.await
}
运行结果:
╰─➤ cargo run
Compiling wmm v0.1.0 (/Users/ponponon/Desktop/code/me/wmm)
Finished dev [unoptimized + debuginfo] target(s) in 0.93s
Running `target/debug/wmm`
Hello world
首先,Rust 中的
Result
是一个枚举,用于返回Error
,而这个是 Rust 错误处理的知识,本身和actix-web
无关。Rust 中函数返回的
Error
必须被处理,这一点和 Golang 中不同。所以
main
之所以需要返回Result
是因为它函数内部的代码返回了Result
,而main
自己没有处理,直接返回出去了。具体
main
为什么要返回Result
,实际上是最后那个.await
干的,可以把main
改成这样:然后就会比较清晰地发现,
server.run()
返回了一个Server
对象,而这个对象在使用await
关键字时,抛出了Result
。在 Rust 中,如果一行代码后面不加
;
,则被当作返回值,这里await
的返回值就是一个Result
。原因会在下面再讲。你如果一定不想返回
Result
,只需要把future.await
改写成future.await.unwrap();
就行了。这个也是 Rust 的异常处理机制之一,unwrap()
不处理异常,而是在遇到异常时直接panic
。回到上面的
await
,这玩意儿为啥会返回Result
?这个问题我这里只能给你简单说明一下方向,因为涉及到了 Rust 的异步原理,有点复杂(我自己也不是非常熟,尴尬)。简单说,
server.run()
会返回一个Server
对象,这个对象的定义如下:看到那个
fut
了没,它是一个Future
类型智能指针,并且泛型参数是io::Result<()>
。而当
Server
作为一个Future
被await
的时候,异步运行时会执行poll
,源码如下:嗯,大概就是这样。