move Closures
Closures move capturam variáveis por valor para o ambiente da closure, o que é necessário para thread::spawn e callbacks de longa duração.
Receita
use std::thread;
fn main() {
let data = vec![1, 2, 3];
// A closure `move` captura `data` por valor.
thread::spawn(move || println!("{:?}", data));
}Quando usar isso: Threads, tokio::spawn, timers e quando a closure pode sobreviver aos empréstimos da stack.
Exemplo de Trabalho
fn spawn_sum(nums: Vec<i32>) -> std::thread::JoinHandle<i32> {
// `nums` é movido para a closure.
std::thread::spawn(move || nums.iter().sum())
}
fn main() {
let h = spawn_sum(vec![1, 2, 3]);
// A thread principal não pode mais usar `nums` após o `spawn`.
println!("{}", h.join().unwrap());
}O que isto demonstra:
numsfoi movido para a closure.- A thread principal não pode usar
numsapós ospawn. JoinHandleretorna o resultado da thread.
Análise Detalhada
move aplica-se a todas as variáveis capturadas, não seletivamente. Use clone antes de move se tanto a thread quanto a thread principal precisarem dos dados.
Armadilhas
movequando um empréstimo funcionaria - Clones extras. Correção: Omitamovepara closures de curta duração.movecopia tiposCopy- Ainda são semânticas de "move", mas os bits são copiados.Arcnecessário para propriedade compartilhada - Múltiplas threads precisam clonarArcantes domove.RefCellentre threads - Não éSend. Correção: UseMutex.- Bloco
async move- Captura a propriedade para o futuro.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
Arc + move | Leitura compartilhada entre threads | Proprietário único |
| Threads com escopo | Emprestar dados da stack | Thread desanexada |
| Envio de canal | Passar a propriedade | Estado compartilhado necessário |
FAQs
move captura tudo?
Sim - a palavra-chave aplica-se ao conjunto de captura inferido.tokio spawn?
Mesmo `move` + `Send` + `'static`.clonar antes do move?
Manter cópia na thread pai.FnOnce após move?
Consumir capturas frequentemente resulta em FnOnce.tipos copy?
Copiados para o ambiente da closure.ref em move?
Ainda move referências próprias (ex: String).threads com escopo?
Pode emprestar sem move - API com escopo.tamanho da closure?
Struct capturada grande aumenta o tamanho da closure.wasm?
thread spawn é limitado - move ainda é para callbacks.lint?
`redundant_clone` em torno de padrões `move`.Relacionados
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.