我正试图用Rust编写基本的网络代码,但遇到了一个我不理解的错误.到目前为止,我一直使用Match语句来错误判断Rust中的所有内容,但是当我try 错误判断TcpStream::Connect()时,我得到了一个意外的错误:

我的代码是:

use std::net::TcpStream;

fn main() {
    let mut server = match TcpStream::connect("127.0.0.1:23456"){
        Ok(x) => x,
        Err(x) => println!("Could not connect to server: {x}"),
    };
}

编译器错误:

error[E0308]: `match` arms have incompatible types
 --> src/main.rs:8:19
  |
6 |       let mut server = match TcpStream::connect("127.0.0.1:23456"){
  |  ______________________-
7 | |         Ok(x) => x,
  | |                  - this is found to be of type `TcpStream`
8 | |         Err(x) => println!("Could not connect to server: {x}"),
  | |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
                        expected struct `TcpStream`, found `()`
9 | |     };
  | |_____- `match` arms have incompatible types
  |

每隔一次我使用Match语句,它就允许我将结果类型分解为OK情况下的返回值(如上所述),或错误情况下的错误字符串.

TcpStream::Connect()确实返回TcpStream,但是为什么编译器坚持错误情况也需要返回TcpStream呢?

推荐答案

match语句的值被赋值为server.

但是,match语句的两个分支返回不同的类型.

  • Ok(x)返回类型为TcpStreamx.
  • Err(x)返回println!()的结果,返回值为().

TcpStream()不兼容.

只需考虑Match语句之后的代码.server的变量应该是多少?当错误发生时,您不会停止执行,您只需println!()并继续.所以something必须写入server变量.

如果您是panic!()而不是println!(),意味着打印和中止,那么它会编译,因为它知道Err事件之后不会继续:

use std::net::TcpStream;

fn main() {
    let mut server = match TcpStream::connect("127.0.0.1:23456") {
        Ok(x) => x,
        Err(x) => panic!("Could not connect to server: {x}"),
    };
}
thread 'main' panicked at 'Could not connect to server: Connection refused (os error 111)', src/main.rs:6:19

也就是说,如果这是你想要的行为,有一个简短的形式来表示:

use std::net::TcpStream;

fn main() {
    let mut server = TcpStream::connect("127.0.0.1:23456").expect("Could not connect to server");
}
thread 'main' panicked at 'Could not connect to server: Os { code: 111, kind: ConnectionRefused, message: "Connection refused" }', src/main.rs:4:60

不过,我建议正确处理该错误.

有很多方法可以做到这一点,所以这一部分将是固执己见的.

我个人喜欢miette(也可以 Select anyhow):

use miette::{Context, IntoDiagnostic};
use std::net::TcpStream;

fn main() -> miette::Result<()> {
    let mut _server = TcpStream::connect("127.0.0.1:23456")
        .into_diagnostic()
        .wrap_err("Could not connect to server.")?;

    // Do something with server

    Ok(())
}
Error: 
  × Could not connect to server.
  ╰─▶ Connection refused (os error 111)

Rust相关问答推荐

为什么我需要在这个代码示例中使用&

当为a Self:IntoIterator设置trait bind `时,获取`a T `不是迭代器"&'"<'>&'

无法在线程之间安全地发送future (&Q;)&错误

使用pyo3::Types::PyIterator的无限内存使用量

为什么Rust不支持带关联常量的特征对象?

如何在嵌套的泛型 struct 中调用泛型方法?

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

不同类型泛型的映射

是否提供Bundle 在可执行文件中的warp中的静态文件?

如何轮询 Pin>?

使用 Option 来分配?

如何处理闭包中的生命周期以及作为参数和返回类型的闭包?

如何在 Rust 中将枚举变体转换为 u8?

在 Rust 中,Weak 如何知道内部值何时被删除?

Rust 中的方法调用有什么区别?

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

在 Rust 中,为什么整数溢出有时会导致编译错误或运行时错误?

只有一个字符被读入作为词法分析器的输入

通用函数中的生命周期扣除和borrow (通用测试需要)

C++ 中的 CRTP 是一种表达其他语言中特征和/或 ADT 的方法吗?