Rust: Programação de Sistemas Segura
Aprenda Rust, a linguagem que garante segurança de memória sem garbage collector
Rust: Programação de Sistemas Segura
Rust é uma linguagem de programação de sistemas que combina performance de baixo nível com garantias de segurança em tempo de compilação. Criada pela Mozilla e lançada em 2010, Rust elimina classes inteiras de bugs relacionados à memória através de seu sistema de ownership único, sem sacrificar a performance.
Por que Rust? Rust foi votada como a “linguagem mais amada” no Stack Overflow Survey por 8 anos consecutivos. Empresas como Microsoft, Google, Amazon e Discord usam Rust em produção.
Conceitos Fundamentais
Ownership, Borrowing e Lifetimes
O sistema de ownership é o coração de Rust:
// Ownership - cada valor tem um único dono
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 é movido para s2
// println!("{}", s1); // ERRO! s1 não é mais válido
println!("{}", s2); // OK
}
// Borrowing - referências imutáveis
fn calcular_tamanho(s: &String) -> usize {
s.len()
}
// Borrowing mutável
fn adicionar_texto(s: &mut String) {
s.push_str(" world");
}
fn main() {
let mut texto = String::from("hello");
// Múltiplas referências imutáveis são permitidas
let r1 = &texto;
let r2 = &texto;
println!("{} e {}", r1, r2);
// Apenas UMA referência mutável por vez
let r3 = &mut texto;
r3.push_str("!");
println!("{}", r3);
}
// Lifetimes - garantem que referências são válidas
fn maior<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
Tipos de Dados
// Tipos primitivos
let inteiro: i32 = 42;
let flutuante: f64 = 3.14;
let booleano: bool = true;
let caractere: char = '🦀';
// Tuplas
let tupla: (i32, f64, &str) = (42, 3.14, "rust");
let (x, y, z) = tupla; // Destructuring
// Arrays (tamanho fixo)
let array: [i32; 5] = [1, 2, 3, 4, 5];
let primeiro = array[0];
// Vectors (tamanho dinâmico)
let mut vec: Vec<i32> = vec![1, 2, 3];
vec.push(4);
// Strings
let s1: &str = "string literal"; // String slice
let s2: String = String::from("owned string");
// HashMap
use std::collections::HashMap;
let mut mapa: HashMap<&str, i32> = HashMap::new();
mapa.insert("chave", 42);
Structs e Enums
// Struct
#[derive(Debug, Clone)]
struct Usuario {
nome: String,
email: String,
idade: u32,
ativo: bool,
}
impl Usuario {
// Construtor
fn novo(nome: String, email: String, idade: u32) -> Self {
Self {
nome,
email,
idade,
ativo: true,
}
}
// Método
fn saudar(&self) -> String {
format!("Olá, {}!", self.nome)
}
// Método mutável
fn desativar(&mut self) {
self.ativo = false;
}
}
// Enum com dados
enum Mensagem {
Sair,
Mover { x: i32, y: i32 },
Escrever(String),
MudarCor(u8, u8, u8),
}
// Pattern matching
fn processar_mensagem(msg: Mensagem) {
match msg {
Mensagem::Sair => println!("Saindo..."),
Mensagem::Mover { x, y } => println!("Movendo para ({}, {})", x, y),
Mensagem::Escrever(texto) => println!("Texto: {}", texto),
Mensagem::MudarCor(r, g, b) => println!("Cor: RGB({}, {}, {})", r, g, b),
}
}
// Option e Result
fn dividir(a: f64, b: f64) -> Option<f64> {
if b == 0.0 { None } else { Some(a / b) }
}
fn ler_arquivo(caminho: &str) -> Result<String, std::io::Error> {
std::fs::read_to_string(caminho)
}
Traits
// Definindo uma trait
trait Resumivel {
fn resumo(&self) -> String;
// Implementação padrão
fn descricao(&self) -> String {
format!("Resumo: {}", self.resumo())
}
}
// Implementando trait
struct Artigo {
titulo: String,
autor: String,
conteudo: String,
}
impl Resumivel for Artigo {
fn resumo(&self) -> String {
format!("{} por {}", self.titulo, self.autor)
}
}
// Trait bounds em generics
fn imprimir_resumo<T: Resumivel>(item: &T) {
println!("{}", item.resumo());
}
// Múltiplas trait bounds
fn processar<T: Resumivel + Clone + std::fmt::Debug>(item: T) {
println!("{:?}", item);
}
// Where clause para legibilidade
fn funcao_complexa<T, U>(t: T, u: U) -> String
where
T: Resumivel + Clone,
U: std::fmt::Display,
{
format!("{}: {}", t.resumo(), u)
}
Tratamento de Erros
use std::fs::File;
use std::io::{self, Read};
// Propagação de erros com ?
fn ler_usuario() -> Result<String, io::Error> {
let mut arquivo = File::open("usuario.txt")?;
let mut conteudo = String::new();
arquivo.read_to_string(&mut conteudo)?;
Ok(conteudo)
}
// Erro customizado
#[derive(Debug)]
enum MeuErro {
Io(io::Error),
Parse(std::num::ParseIntError),
Customizado(String),
}
impl From<io::Error> for MeuErro {
fn from(err: io::Error) -> Self {
MeuErro::Io(err)
}
}
// Usando anyhow para simplificar
// use anyhow::{Context, Result};
// fn funcao() -> Result<()> {
// let arquivo = File::open("config.txt")
// .context("Falha ao abrir arquivo de configuração")?;
// Ok(())
// }
Concorrência
use std::thread;
use std::sync::{Arc, Mutex};
// Threads básicas
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("Thread: {}", i);
}
});
for i in 1..5 {
println!("Main: {}", i);
}
handle.join().unwrap();
}
// Compartilhando dados entre threads
fn contador_compartilhado() {
let contador = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let contador = Arc::clone(&contador);
let handle = thread::spawn(move || {
let mut num = contador.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Resultado: {}", *contador.lock().unwrap());
}
// Async/await com tokio
// use tokio;
//
// #[tokio::main]
// async fn main() {
// let response = reqwest::get("https://api.exemplo.com")
// .await
// .unwrap()
// .text()
// .await
// .unwrap();
// println!("{}", response);
// }
Ferramentas do Ecossistema
| Ferramenta | Propósito |
|---|---|
| cargo | Gerenciador de pacotes e build |
| rustfmt | Formatador de código |
| clippy | Linter com dicas avançadas |
| rust-analyzer | LSP para IDEs |
Checklist de Aprendizado
- Entender ownership, borrowing e lifetimes
- Dominar structs, enums e pattern matching
- Aprender traits e generics
- Estudar tratamento de erros com Result e Option
- Explorar concorrência e async/await
- Construir um projeto CLI
- Contribuir para projetos Rust open source
Recursos Essenciais
Citação
“Rust é uma linguagem que respeita o tempo e a inteligência do desenvolvedor.” - Steve Klabnik
Rust pode parecer desafiador no início, mas as garantias de segurança que oferece valem o investimento!