如何修复由变量赋值引起的以下移动错误?

huangapple go评论59阅读模式
英文:

How to fix the following move error caused by variable assignment?

问题

以下是翻译好的部分:

以下的`Screen`结构体有处理`Input`枚举的方法:

#[derive(Debug)]
pub enum Input {
    Text(String),
    None,
    Exit,
}

#[derive(Debug)]
pub enum InputError {
    NotUTF8(Vec<u8>),
    EmptyString,
    IoError(std::io::Error),
}

struct Screen {
    stdout: Vec<u8>,
}

impl Screen {
    fn new(stdout: Vec<u8>) -> Self {
        Screen { stdout }
    }

    fn print_input(self, input: Input) {
        match input {
            Input::Text(text) => {
                println!("{}", &text);
            }
            Input::None => {
                println!("None");
            } 
            Input::Exit => {
                println!("Exit");
            }
        }
    }

    fn handle_input(self, prompt: Option<String>) -> Result<Input, InputError> {
        match prompt {
            Some(_) => {
                let input = get_input()?;
                // 处理提示信息

                Ok(input)
            }
            None => {
                Ok(Input::None)
            }
        }
    }
}

fn get_input() -> Result<Input, InputError> {
    let input = "Text".to_owned();

    Ok(Input::Text(input))
}

fn main() {
    let screen = Screen::new(Vec::new());
    let prompt = Some("Prompt".to_string());
    let input = screen.handle_input(prompt);

    screen.print_input(input.unwrap());
}

正如你所看到的,在`main()`函数中存在移动问题:

60 |     let screen = Screen::new(Vec::new());
   |         ------ 移动发生在这里,因为`screen`的类型是`Screen`,它没有实现`Copy`特性
61 |     let prompt = Some("Prompt".to_string());
62 |     let input = screen.handle_input(prompt);
   |                        -------------------- 由于这个方法调用导致`screen`被移动了
63 |
64 |     screen.handle_input_result(input.unwrap());
   |     ^^^^^^ 在移动之后在这里使用了值
   |
注意:`Screen::handle_input`方法接管了接收者`self`的所有权,因此移动了`screen`

如何修复这个问题?

请注意,上述翻译并没有包含代码部分。如果你需要完整的代码翻译,请提供额外的信息,我将为你提供完整的翻译。

英文:

The following Screen struct has methods that handle the Input enum:

#[derive(Debug)]
pub enum Input {
Text(String),
None,
Exit,
}
#[derive(Debug)]
pub enum InputError {
NotUTF8(Vec&lt;u8&gt;),
EmptyString,
IoError(std::io::Error),
}
struct Screen {
stdout: Vec&lt;u8&gt;,
}
impl Screen {
fn new(stdout: Vec&lt;u8&gt;) -&gt; Self {
Screen { stdout }
}
fn print_input(self, input: Input) {
match input {
Input::Text(text) =&gt; {
println!(&quot;{}&quot;, &amp;text);
}
Input::None =&gt; {
println!(&quot;None&quot;);
} 
Input::Exit =&gt; {
println!(&quot;Exit&quot;);
}
}
}
fn handle_input(self, prompt: Option&lt;String&gt;) -&gt; Result&lt;Input, InputError&gt; {
match prompt {
Some(_) =&gt; {
let input = get_input()?;
// do something with prompt
Ok(input)
}
None =&gt; {
Ok(Input::None)
}
}
}
}
fn get_input() -&gt; Result&lt;Input, InputError&gt; {
let input = &quot;Text&quot;.to_owned();
Ok(Input::Text(input))
}
fn main() {
let screen = Screen::new(Vec::new());
let prompt = Some(&quot;Prompt&quot;.to_string());
let input = screen.handle_input(prompt);
screen.print_input(input.unwrap());
}

As you can see, there's a move problem in main():

60 |     let screen = Screen::new(Vec::new());
|         ------ move occurs because `screen` has type `Screen`, which does not implement the `Copy` trait
61 |     let prompt = Some(&quot;Prompt&quot;.to_string());
62 |     let input = screen.handle_input(prompt);
|                        -------------------- `screen` moved due to this method call
63 |
64 |     screen.handle_input_result(input.unwrap());
|     ^^^^^^ value used here after move
|
note: `Screen::handle_input` takes ownership of the receiver `self`, which moves `screen`
--&gt; src/main.rs:24:21
|
24 |     fn handle_input(self, prompt: Option&lt;String&gt;) -&gt; Result&lt;Input, InputError&gt; {
|     
^^^^

How to fix it?

答案1

得分: 3

你将 self 传递给你的方法时是按值传递的,因此移动了你的 Screen 实例。你的方法不需要拥有 self 的所有权,所以可以改为通过引用传递 (&self),从而修复所有权错误:

#[derive(Debug)]
pub enum Input {
    Text(String),
    None,
    Exit,
}

#[derive(Debug)]
pub enum InputError {
    NotUTF8(Vec<u8>),
    EmptyString,
    IoError(std::io::Error),
}

struct Screen {
    stdout: Vec<u8>,
}

impl Screen {
    fn new(stdout: Vec<u8>) -> Self {
        Screen { stdout }
    }

    fn print_input(&self, input: Input) {
        match input {
            Input::Text(text) => {
                println!("{}", &text);
            }
            Input::None => {
                println!("None");
            } 
            Input::Exit => {
                println!("Exit");
            }
        }
    }

    fn handle_input(&self, prompt: Option<String>) -> Result<Input, InputError> {
        match prompt {
            Some(_) => {
                let input = get_input()?;
                // 处理提示的内容

                Ok(input)
            }
            None => {
                Ok(Input::None)
            }
        }
    }
}

fn get_input() -> Result<Input, InputError> {
    let input = "Text".to_owned();

    Ok(Input::Text(input))
}

fn main() {
    let screen = Screen::new(Vec::new());
    let prompt = Some("Prompt".to_string());
    let input = screen.handle_input(prompt);

    screen.print_input(input.unwrap());
}

Playground.

英文:

You pass self to your methods by value, thus moving your Screen instance. Your methods don't require ownership over self, so you can just pass it by reference instead (&amp;self), fixing your ownership error:

#[derive(Debug)]
pub enum Input {
Text(String),
None,
Exit,
}
#[derive(Debug)]
pub enum InputError {
NotUTF8(Vec&lt;u8&gt;),
EmptyString,
IoError(std::io::Error),
}
struct Screen {
stdout: Vec&lt;u8&gt;,
}
impl Screen {
fn new(stdout: Vec&lt;u8&gt;) -&gt; Self {
Screen { stdout }
}
fn print_input(&amp;self, input: Input) {
match input {
Input::Text(text) =&gt; {
println!(&quot;{}&quot;, &amp;text);
}
Input::None =&gt; {
println!(&quot;None&quot;);
} 
Input::Exit =&gt; {
println!(&quot;Exit&quot;);
}
}
}
fn handle_input(&amp;self, prompt: Option&lt;String&gt;) -&gt; Result&lt;Input, InputError&gt; {
match prompt {
Some(_) =&gt; {
let input = get_input()?;
// do something with prompt
Ok(input)
}
None =&gt; {
Ok(Input::None)
}
}
}
}
fn get_input() -&gt; Result&lt;Input, InputError&gt; {
let input = &quot;Text&quot;.to_owned();
Ok(Input::Text(input))
}
fn main() {
let screen = Screen::new(Vec::new());
let prompt = Some(&quot;Prompt&quot;.to_string());
let input = screen.handle_input(prompt);
screen.print_input(input.unwrap());
}

Playground.

huangapple
  • 本文由 发表于 2023年6月11日 21:59:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76450825.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定