Rust — Cheat Sheet

Tag: rust, systems, safety, compiler, cargo

Livello: intermedio

TL;DR: Rust è un linguaggio di programmazione di sistema che offre sicurezza della memoria e alte prestazioni garantendo l'assenza di data race tramite i concetti di ownership e borrowing a tempo di compilazione.

Concetti chiave

-

L'ownership impone che ogni valore allocato in memoria abbia un unico proprietario alla volta.

-

Quando il proprietario esce dallo scope, il valore viene automaticamente deallocato senza bisogno di garbage collection.

-

Il borrowing permette di creare referenze temporanee ai dati senza trasferirne la proprietà originaria.

-

Il borrow checker assicura che si possa avere una singola referenza mutabile oppure infinite referenze immutabili, ma mai entrambe.

-

I lifetime vengono analizzati dal compilatore per garantire che le referenze non sopravvivano mai alla durata di vita dei dati a cui puntano.

-

Il costrutto match fornisce un pattern matching esaustivo che costringe a gestire tutti i casi possibili.

-

I trait agiscono come interfacce per definire comportamenti condivisi che strutture dati diverse possono implementare.

-

La gestione degli errori è esplicita e si affida agli enumeratori Result per errori recuperabili e Option per valori assenti.

-

Cargo agisce da ecosistema unificato occupandosi della risoluzione delle dipendenze, della compilazione e dell'esecuzione dei test.

Domande tipiche e risposte pronte

-

Q: Qual è la differenza principale tra String e &str?R: String possiede i propri dati allocati dinamicamente sull'heap e può essere mutata, mentre &str è una string slice che rappresenta una vista prestata e immutabile.

-

Q: Come garantisce Rust la sicurezza nel multithreading?R: Tramite i trait Send e Sync integrati nel sistema dei tipi; il compilatore impedisce il passaggio di referenze non sincronizzate e blocca i data race.

-

Q: Cosa rappresentano i concetti di smart pointer in questo linguaggio?R: Sono strutture dati come Box, Rc o Arc che allocano dati sull'heap e implementano internamente i trait Deref e Drop per la gestione automatica.

Insidie e errori comuni

-

Provare a modificare il valore di una variabile di base senza averla dichiarata esplicitamente con la keyword mut.

-

Chiamare unwrap() direttamente su Result o Option invece di gestire la deviazione di flusso in modo sicuro.

-

Passare una variabile a una chiusura senza gestire correttamente il trasferimento di ownership o il borrowing esplicito.

Snippet e comandi

// Propagazione degli errori tramite operatore interrogativo
use std::fs::File;
use std::io::{self, Read};

fn read_config() -> Result<String, io::Error> {
    let mut file = File::open("config.toml")?;
    let mut config = String::new();
    file.read_to_string(&mut config)?;
    Ok(config)
}

Bash

# Comandi standard del ciclo di sviluppo
cargo init
cargo check
cargo clippy
cargo build --release
cargo run

Da ripassare

-

[ ] Sintassi delle annotazioni esplicite dei lifetime per funzioni con parametri multipli.

-

[ ] Utilizzo avanzato di Arc combinato con Mutex per la mutabilità interna in thread separati.

-

[ ] Definizione e implementazione di trait custom con tipi associati.

Jarvis Interviews
Jarvis