Rust中重新赋值Option<T>时如何避免值被移动?
Rust管道命令执行中的"use of moved value"错误解决
问题根源
你的代码错误核心在于**Option<Stdio>的所有权管理不当**:
- 直接通过
match取出previous_command内部的值,导致原变量的所有权被转移,后续无法再使用 - 最后一个命令分支中,重复使用已被移动的
previous_command(先match取stdin,又调用unwrap())
解决思路与修改代码
使用Option::take()安全管理所有权,配合map简化类型转换,修复重复使用变量的问题:
use std::env; use std::fs; use std::fs::File; use std::fs::OpenOptions; use std::io::stdin; use std::io::stdout; use std::io::ErrorKind; use std::io::Write; use std::io::{self, prelude::*, BufReader}; use std::path::Path; use std::process::Child; use std::process::Command; use std::process::Stdio; use std::str; fn process_line(input: &str) -> String { let mut commands = input.trim().split(" | ").peekable(); let mut previous_command = None; let mut resultat = String::new(); while let Some(command) = commands.next() { let mut parts = command.trim().split_whitespace(); let command = parts.next().unwrap(); let args = parts; if commands.peek().is_some() { // 取出上一个命令的输出作为当前输入,无则继承系统stdin let stdin = previous_command.take().unwrap_or(Stdio::inherit()); let stdout = Stdio::piped(); match Command::new(command) .args(args) .stdout(stdout) .stdin(stdin) .spawn() { Ok(child) => { // 将当前命令的stdout转为Stdio,保存给下一个命令使用 previous_command = child.stdout.map(Stdio::from); } Err(e) => { eprintln!("Err: {}", e); previous_command = None; } }; } else { // 最后一个命令,取出上一个命令的输出作为输入 let stdin = previous_command.take().unwrap_or(Stdio::inherit()); let output = Command::new(command) .args(args) .stdin(stdin) .output() .expect("Failed to execute final command"); resultat.push_str( str::from_utf8(&output.stdout) .expect("Could not convert command output to string"), ); } } resultat }
关键修改说明
previous_command.take():安全取出Option内部的值,同时将原变量置为None,彻底避免所有权移动冲突child.stdout.map(Stdio::from):利用map直接将Option<ChildStdout>转为Option<Stdio>,比unwrap()更安全(避免panic)- 最后一个命令分支中,直接使用取出的
stdin,不再重复操作previous_command,解决重复移动的问题
内容的提问来源于stack exchange,提问作者squi
相关产品推荐
相关产品推荐

