Rust 类型推断错误

Rust Type Inference Error

我正在通过 TCP 编写聊天服务器作为学习项目。我一直在修补 ws crate today, but I've come across an issue. This is the code I wrote, modifying their server example.

extern crate ws;
extern crate env_logger;

use ws::listen;

fn main() {
    // Setup logging
    env_logger::init().unwrap();

    // Listen on an address and call the closure for each connection
    if let Err(error) = listen("127.0.0.1:3012", |out| {
        let mut message: String;
        // The handler needs to take ownership of out, so we use move
        move |message| {
            message = message.trim();
            // Handle messages received on this connection
            println!("Server got message '{}'. ", message);

            // Use the out channel to send messages back
            out.send(message)
        }

    }) {
        // Inform the user of failure
        println!("Failed to create WebSocket due to {:?}", error);
    }
}

当我尝试编译它时出现错误:

error: the type of this value must be known in this context
  --> src/main.rs:15:23
   |
15 |             message = message.trim();
   |                       ^^^^^^^^^^^^^^

为什么会这样?我该如何解决这个问题?

move |message| 隐藏了您在闭包外声明的 message 变量。所以在闭包中.. message 据说是 ws::Message ...除非你这样做了:

message = message.trim();

编译器 "oh no! trim()? That doesn't exist for ws::Message".. 所以现在它不太知道要做什么。

选项 1

第一个修复涉及将 trim() 调用委托给发送消息的客户端。

解决方法是不对该闭包中的消息内容做任何假设。如果你保留这个:

move |message|

..但删除 trim() 调用,编译器会愉快地将其类型推断为 ws::Message 并将构建:

if let Err(error) = listen("127.0.0.1:3012", |out| {
    // The handler needs to take ownership of out, so we use move
    move |message| {
        // --- REMOVED trim() call ---

        // Handle messages received on this connection
        println!("Server got message '{}'. ", message);

        // Use the out channel to send messages back
        out.send(message)
    }
}

这让您可以选择将 trim() 调用委托给客户端。

选项 2

选项 2 涉及检查您收到的消息类型,并确保您 trim 只有当它是文本时:

// The handler needs to take ownership of out, so we use move
move |mut message: ws::Message| {
    // Only do it if the Message is text
    if message.is_text() {
        message = ws::Message::Text(message.as_text().unwrap().trim().into());
    }

    // Handle messages received on this connection
    println!("Server got message '{}'. ", message);

    // Use the out channel to send messages back
    out.send(message)
}

这可能比需要的更冗长..但希望它能告诉您原始代码片段的实际问题是什么。