这在任何语言中都应该是一项微不足道的任务.这不适用于Rust.
use std::collections::HashMap;
fn do_it(map: &mut HashMap<String, String>) {
for (key, value) in map {
println!("{} / {}", key, value);
map.remove(key);
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
这是编译器错误:
error[E0382]: use of moved value: `*map`
--> src/main.rs:6:9
|
4 | for (key, value) in map {
| --- value moved here
5 | println!("{} / {}", key, value);
6 | map.remove(key);
| ^^^ value used here after move
|
= note: move occurs because `map` has type `&mut std::collections::HashMap<std::string::String, std::string::String>`, which does …Run Code Online (Sandbox Code Playgroud) 我正在Rust中创建一个小的ncurses应用程序,需要与子进程通信.我已经有了一个用Common Lisp编写的原型; 这里的gif 将有希望展示我想做的事情.我正在尝试重写它,因为CL为这么小的工具使用了大量的内存.
我之前没有使用过Rust(或其他低级语言),而且我在弄清楚如何与子进程交互时遇到了一些麻烦.
我目前正在做的大致是这样的:
创建流程:
let mut program = match Command::new(command)
.args(arguments)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
{
Ok(child) => child,
Err(_) => {
println!("Cannot run program '{}'.", command);
return;
}
};
Run Code Online (Sandbox Code Playgroud)将它传递给无限(直到用户退出)循环,该循环读取并处理输入并像这样监听输出(并将其写入屏幕):
fn listen_for_output(program: &mut Child, output_viewer: &TextViewer) {
match program.stdout {
Some(ref mut out) => {
let mut buf_string = String::new();
match out.read_to_string(&mut buf_string) {
Ok(_) => output_viewer.append_string(buf_string),
Err(_) => return,
};
}
None => return,
};
}
Run Code Online (Sandbox Code Playgroud)read_to_string然而,调用阻止程序直到进程退出.从我所看到的read_to_end,read似乎也阻止.如果我尝试运行类似于ls哪个退出的东西,它可以工作,但是有些东西不能退出, …
use std::thread;
use tokio::task; // 0.3.4
#[tokio::main]
async fn main() {
thread::spawn(|| {
task::spawn(async {
println!("123");
});
})
.join();
}
Run Code Online (Sandbox Code Playgroud)
编译时我收到警告:
warning: unused `std::result::Result` that must be used
--> src/main.rs:6:5
|
6 | / thread::spawn(|| {
7 | | task::spawn(async {
8 | | println!("123");
9 | | });
10 | | })
11 | | .join();
| |____________^
|
= note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled
Run Code Online (Sandbox Code Playgroud)
执行时出现错误: …
我想轮询一个异步函数:
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
some_function().await;
}
Run Code Online (Sandbox Code Playgroud)
我目前正在激活所有功能:
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
some_function().await;
}
Run Code Online (Sandbox Code Playgroud)
其中哪些是必要的?
tokio = { version = "1.4.0", features = ["full"] }
Run Code Online (Sandbox Code Playgroud) 我有一个与远程服务器通信的 Tokio 客户端,并且应该保持连接永久有效。我已经实现了初始身份验证握手,发现当我的测试终止时,我得到了一个奇怪的恐慌:
---- test_connect_without_database stdout ----
thread 'test_connect_without_database' panicked at 'Cannot drop a runtime in a context where blocking is not allowed. This happens when a runtime is dropped from within an asynchronous context.', /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.3.5/src/runtime/blocking/shutdown.rs:51:21
Run Code Online (Sandbox Code Playgroud)
对于可能导致这种情况的原因,我完全不知所措,所以我不知道要为上下文添加哪些其他代码位。
这是我最小的可重现示例(playground):
use std::cell::RefCell;
use std::net::{IpAddr, SocketAddr};
use tokio::net::TcpStream;
use tokio::prelude::*;
use tokio::runtime;
#[derive(PartialEq, Debug)]
pub struct Configuration {
/// Database username.
username: String,
/// Database password.
password: String,
/// Database name.
db_name: String,
/// IP address for the remove server.
address: …Run Code Online (Sandbox Code Playgroud) 异步示例很有用,但作为Rust和Tokio的新手,我正在努力研究如何一次执行N个请求,使用向量中的URL,并为每个URL创建响应HTML的迭代器作为字符串.
怎么可以这样做?
我正在尝试连接到数据库:
extern crate tokio; // 0.2.6, features = ["full"]
extern crate tokio_postgres; // 0.5.1
use futures::executor;
use tokio_postgres::NoTls;
fn main() {
let fut = async {
let (client, connection) = match tokio_postgres::connect("actual stuff", NoTls).await {
Ok((client, connection)) => (client, connection),
Err(e) => panic!(e),
};
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
let rows = match client
.query(
"SELECT $1 FROM planet_osm_point WHERE $1 IS NOT NULL LIMIT 100",
&[&"name"],
)
.await
{ …Run Code Online (Sandbox Code Playgroud) 我有一个async fn返回类型,并希望Drop在调用另一个async函数的类型上实现。目前尚不清楚如何执行此操作,而且我在文档中找不到任何内容。我发现的最有启发性的文章是withoutboats 的Asynchronous Destructors,但我真的不明白其中的道理,也不明白这个特性在哪里。
我正在研究和使用 Rust,async/.await用 Rust 编写一个服务,该服务将从一些 websocket 中提取数据并使用该数据执行某些操作。我的一位同事(他在 C# 中做了类似的“数据提要导入”)告诉我异步处理这些提要,因为线程的性能会很差。
据我了解,要在 Rust 中执行任何异步操作,您需要一个运行时(例如 Tokio)。在检查了我发现的关于该主题的大多数代码后,似乎先决条件是:
#[tokio::main]
async fn main() {
// ...
}
Run Code Online (Sandbox Code Playgroud)
它提供了管理我们的async代码所需的运行时。我得出这个结论是因为你不能.await在不是async函数或块的作用域中使用。
这引出了我的主要问题:如果打算在 Rust 中使用async,你是否总是需要async fn main()如上所述的?如果是这样,您如何构建同步代码?结构体可以async实现方法和函数吗(或者甚至应该)?
所有这些都源于我编写此服务的最初方法,因为我设想的方式是拥有某种可以处理多个 websocket feed 的结构,如果它们需要异步完成,那么通过这种逻辑,该结构将具有要有async逻辑在里面。
我想要await一个async在迭代器中使用的闭包内的函数。需要闭包的函数在结构体实现中被调用。我无法弄清楚如何做到这一点。
这段代码模拟了我正在尝试做的事情:
struct MyType {}
impl MyType {
async fn foo(&self) {
println!("foo");
(0..2).for_each(|v| {
self.bar(v).await;
});
}
async fn bar(&self, v: usize) {
println!("bar: {}", v);
}
}
#[tokio::main]
async fn main() {
let mt = MyType {};
mt.foo().await;
}
Run Code Online (Sandbox Code Playgroud)
显然,这将不起作用,因为闭包不是async,给我:
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> src/main.rs:8:13
|
7 | (0..2).for_each(|v| {
| --- this is not `async`
8 | self.bar(v).await;
| ^^^^^^^^^^^^^^^^^ only allowed inside `async` …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建最简单的示例,async fn hello()最终可以打印出Hello World!. 这应该在没有任何外部依赖的情况下发生tokio,就像普通的 Rust 和std. 如果我们可以在不使用unsafe.
#![feature(async_await)]
async fn hello() {
println!("Hello, World!");
}
fn main() {
let task = hello();
// Something beautiful happens here, and `Hello, World!` is printed on screen.
}
Run Code Online (Sandbox Code Playgroud)
async/await这仍然是一个夜间功能,在可预见的未来可能会发生变化。Future实现,我知道tokio.我模糊的理解是,首先,我需要完成Pin任务。所以我继续前进
let pinned_task = Pin::new(&mut task);
Run Code Online (Sandbox Code Playgroud)
但
the trait `std::marker::Unpin` is not implemented for `std::future::GenFuture<[static generator@src/main.rs:7:18: 9:2 {}]>`
Run Code Online (Sandbox Code Playgroud)
所以我想,当然,我可能需要Box它,所以我确定它不会在内存中移动。有点令人惊讶的是,我得到了同样的错误。
到目前为止我能得到的是 …
我需要探索一个目录及其所有子目录。我可以通过递归以同步方式轻松浏览目录:
use failure::Error;
use std::fs;
use std::path::Path;
fn main() -> Result<(), Error> {
visit(Path::new("."))
}
fn visit(path: &Path) -> Result<(), Error> {
for e in fs::read_dir(path)? {
let e = e?;
let path = e.path();
if path.is_dir() {
visit(&path)?;
} else if path.is_file() {
println!("File: {:?}", path);
}
}
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用tokio_fs以下异步方式执行相同操作时:
use failure::Error; // 0.1.6
use futures::Future; // 0.1.29
use std::path::PathBuf;
use tokio::{fs, prelude::*}; // 0.1.22
fn visit(path: PathBuf) -> impl Future<Item = (), Error = Error> …Run Code Online (Sandbox Code Playgroud) 有没有办法使用#[tokio::main]tokio 0.2 中的属性指定单线程运行时?该文档似乎没有这方面的示例。
编辑:我想找到一种方法来设置 tokio 运行时,以便rustc知道tokio:spawn()不会是一个新线程。
rust ×12
rust-tokio ×7
asynchronous ×4
async-await ×3
future ×3
blocking ×1
filesystems ×1
hashmap ×1
io ×1
iteration ×1
mutability ×1
process ×1
pty ×1
reqwest ×1