main în Rust

Funcția cu care începe orice program Rust: este apelată automat la pornire, iar programul se termină când ea se termină.

Sintaxă
fn main() {
    // codul programului
}

fn main() -> Result<(), E> {   // E implementează Debug
    // ...
    Ok(())
}

Ce face main

Orice program executabil Rust are o funcție main, fără parametri. Când pornești programul, Rust face câteva pregătiri și apelează main. Când main se termină, programul se oprește cu codul de ieșire 0 (succes).

Spre deosebire de C, main nu primește argumentele din linia de comandă: le citești cu std::env::args(). Codul de ieșire nu se returnează ca număr; dacă vrei un cod anume, folosești std::process::exit(cod).

main poate returna și Result<(), E>. Atunci poți folosi operatorul ? direct în main: dacă apare o eroare, programul afișează Error: ... (forma Debug a erorii) pe ieșirea de eroare și se termină cu codul 1.

Ce returnează

Nimic (()) în forma obișnuită. În forma cu Result: Ok(()) înseamnă cod de ieșire 0, Err(e) înseamnă cod de ieșire 1.

Exemple

Exemplul 1: Cel mai mic program care afișează ceva

println! este un macro (se recunoaște după !) care afișează textul și trece la rândul următor.

fn main() {
    println!("Salut, lume!");
    println!("Bine ai venit pe dexblog.ro");
}

Rezultat

Salut, lume!
Bine ai venit pe dexblog.ro

Exemplul 2: Argumentele din linia de comandă

Programul a fost pornit fără argumente, deci std::env::args() conține doar numele programului și bucla nu afișează nimic. Rulat cu cargo run -- Ana Iași, ar afișa cele două argumente.

fn main() {
    let argumente: Vec<String> = std::env::args().skip(1).collect();
    println!("Argumente primite: {}", argumente.len());
    for (i, arg) in argumente.iter().enumerate() {
        println!("argumentul {}: {}", i + 1, arg);
    }
}

Rezultat

Argumente primite: 0

Exemplul 3: main care returnează Result

Textul „douăzeci” nu este un număr, deci parse() dă o eroare, iar ? o returnează din main. Rust afișează eroarea cu Error: în față, iar programul se termină cu codul 1.

use std::num::ParseIntError;

fn main() -> Result<(), ParseIntError> {
    let varsta: u32 = "douăzeci".parse()?;
    println!("Vârsta: {varsta}");
    Ok(())
}

Rezultat (programul se oprește cu codul 1)

Error: ParseIntError { kind: InvalidDigit }

Greșeli frecvente

  • Cauți argumentele ca parametri ai lui main (fn main(args: Vec<String>)). Nu se compilează: main nu are parametri, iar argumentele vin din std::env::args().
  • Returnezi un număr din main ca în C (fn main() -> i32). Rust acceptă doar () sau un tip care implementează Termination (de exemplu Result, ExitCode).
  • Folosești std::process::exit în mijlocul programului fără să știi că oprește imediat totul: valorile nu mai sunt eliberate (Drop nu se mai apelează), deci un fișier scris prin BufWriter poate rămâne incomplet.

Comenzi înrudite

  • fn: Declară o funcție. Tipul fiecărui parametru este obligatoriu, iar ultima expresie fără punct și virgulă este valoarea returnată.
  • println! și print!: Afișează text pe ieșirea standard: println! adaugă la final un rând nou, print! nu. Acoladele {} sunt înlocuite cu valori.
  • operatorul ?: Pus după un Result sau Option: dă valoarea dacă totul e bine, altfel returnează imediat eroarea (sau None) din funcția curentă.
  • cargo new: Creează un proiect Rust nou: directorul, Cargo.toml, src/main.rs (sau src/lib.rs) și un depozit git.
  • cargo run: Compilează proiectul dacă s-a schimbat ceva și pornește programul. Argumentele de după – sunt trimise programului.