once_cell para Rust: guia completo com exemplos práticos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Biblioteca once_cell para Rust: inicialização tardia e células únicas

O que é e por que usar

A biblioteca once_cell é uma das mais populares e úteis do ecossistema Rust, projetada para implementar o padrão de inicialização tardia (lazy initialization) e criar células únicas (once cells). Ela fornece dois tipos principais: OnceCell e Lazy, que resolvem um problema fundamental — criar um valor de forma adiada, que é inicializado apenas uma vez no primeiro acesso.

Por que isso é necessário? No Rust, como em qualquer outra linguagem, é comum surgir situações onde criar um objeto é uma operação cara (por exemplo, ler um arquivo de configuração, estabelecer uma conexão com banco de dados, carregar um dicionário grande). Se esse objeto não for necessário imediatamente ao iniciar o programa, mas apenas em condições específicas, sua inicialização pode ser adiada. O once_cell faz isso de forma segura e eficiente, garantindo que a inicialização ocorra exatamente uma vez, mesmo com acesso concorrente de várias threads.

Antes do once_cell ser incorporado à biblioteca padrão do Rust (a partir da versão 1.70.0 com std::cell::OnceCell e std::sync::OnceLock), esta biblioteca era o padrão de facto para inicialização tardia. Ela continua relevante hoje devido à sua maturidade, amplo conjunto de funcionalidades e compatibilidade com versões anteriores. A biblioteca oferece não apenas versões thread-safe (sync), mas também versões single-thread (unsync) dos tipos, permitindo evitar a sobrecarga de sincronização onde ela não é necessária.

Instalação

Para usar o once_cell, adicione-o às dependências do seu projeto no Cargo.toml:

[dependencies]
once_cell = "1.20"

Ou execute o comando:

cargo add once_cell

Depois disso, você pode importar os tipos necessários:

use once_cell::sync::{OnceCell, Lazy};
// ou para uso single-thread:
use once_cell::unsync::{OnceCell as UnsyncOnceCell, Lazy as UnsyncLazy};

Início rápido

Um exemplo mínimo funcional usando Lazy para inicialização tardia de uma variável estática:

use once_cell::sync::Lazy;
use std::collections::HashMap;

// A variável estática será inicializada apenas no primeiro acesso
static CONFIG: Lazy<HashMap<String, String>> = Lazy::new(|| {
    println!("Inicializando configuração...");
    let mut map = HashMap::new();
    map.insert("host".to_string(), "localhost".to_string());
    map.insert("port".to_string(), "8080".to_string());
    map
});

fn main() {
    // Primeiro acesso — a inicialização ocorre aqui
    println!("Host: {}", CONFIG.get("host").unwrap());
    
    // Segundo acesso — a inicialização NÃO ocorre, usa o valor em cache
    println!("Porta: {}", CONFIG.get("port").unwrap());
}

Saída do programa:

Inicializando configuração...
Host: localhost
Porta: 8080

Principais métodos e funções

Vamos explorar 8 métodos e funções principais da biblioteca once_cell com exemplos de uso.

1. OnceCell::new()

Assinatura: pub const fn new() -> OnceCell<T>

O que faz: Cria uma nova célula vazia que ainda não contém um valor.

use once_cell::sync::OnceCell;

let cell: OnceCell<i32> = OnceCell::new();
assert!(cell.get().is_none()); // A célula está vazia

2. OnceCell::set()

Assinatura: pub fn set(&self, value: T) -> Result<(), T>

Recommendations