Galleria mappe mentale Padroneggiare RUST 2a edizione
Questa è una mappa mentale su come padroneggiare RUST. Attraverso i passaggi e i suggerimenti precedenti, puoi migliorare gradualmente le tue capacità di programmazione di Rust e goderti la sicurezza della memoria e le prestazioni efficienti offerte da Rust.
Modificato alle 2024-04-04 15:14:48個人求職簡歷模板的暗黑配色方案,包括個人簡介、職業規劃、行業經驗、自我評價等多個部分,讓你的簡歷更出彩。使用模板可以極大地提高效率,用戶不需要從頭開始設計結構和內容,只需在模板的基礎上填寫或添加自己的信息即可,這樣可以節省大量的時間和精力,歡迎參考使用!持續分享給大家……
Se non sai come scrivere un articolo, sarai nei guai come manager dei sistemi informativi. Una guida passo passo su come scrivere un documento sulla gestione del rischio. Se ne hai bisogno, ritiralo velocemente!
Il programma dietetico formula un programma dietetico scientifico e ragionevole per soddisfare i nutrienti e l'energia richiesti dal corpo, mantenendo così una buona salute e una buona postura.
個人求職簡歷模板的暗黑配色方案,包括個人簡介、職業規劃、行業經驗、自我評價等多個部分,讓你的簡歷更出彩。使用模板可以極大地提高效率,用戶不需要從頭開始設計結構和內容,只需在模板的基礎上填寫或添加自己的信息即可,這樣可以節省大量的時間和精力,歡迎參考使用!持續分享給大家……
Se non sai come scrivere un articolo, sarai nei guai come manager dei sistemi informativi. Una guida passo passo su come scrivere un documento sulla gestione del rischio. Se ne hai bisogno, ritiralo velocemente!
Il programma dietetico formula un programma dietetico scientifico e ragionevole per soddisfare i nutrienti e l'energia richiesti dal corpo, mantenendo così una buona salute e una buona postura.
Competente in RUST
Capitolo 1 Iniziare con Rust
1.1 Cos'è Rust e perché ne hai bisogno
Rust è un linguaggio di programmazione veloce, altamente simultaneo, sicuro e potente originariamente creato e rilasciato nel 2006 da Graydon Hoare. Ora è un linguaggio open source, gestito e sviluppato principalmente dal team Mozilla e da molti membri della comunità open source.
Rust ha un sito web di sviluppo open source su GitHub e il suo slancio di sviluppo è molto rapido. Le nuove funzionalità vengono aggiunte al linguaggio attraverso un processo RFC (Request For Comment) guidato dalla comunità, in cui chiunque può inviare nuove funzionalità e quindi descriverle in dettaglio in un documento RFC. Viene quindi cercato il consenso sulla RFC e, se viene raggiunto, la funzionalità entra nella fase di implementazione.
Rust esiste come linguaggio statico e fortemente tipizzato. Gli attributi statici indicano che il compilatore dispone di informazioni su tutte le variabili e i tipi rilevanti in fase di compilazione ed esegue molti controlli in fase di compilazione, lasciando solo una piccola quantità di controllo del tipo in fase di esecuzione.
1.2 Installa la catena di strumenti Rust
ruggine.rs
1.3 Introduzione a Rust
1.3.1 Tipi primitivi
bool
Questi sono valori booleani comuni che possono essere veri o falsi.
car
carattere
numero intero
Questo tipo è caratterizzato dalla larghezza di bit. La lunghezza massima supportata da Rust è 128 bit.
issize
Un intero con segno di dimensione variabile (la dimensione dipende dalla dimensione del puntatore sottostante).
utilizzare
Intero senza segno di dimensione variabile (la dimensione dipende dalla dimensione del puntatore sottostante).
f32
tipo a virgola mobile f32 bit
f64
tipo a virgola mobile f64 bit
[N]
Una matrice di dimensioni fisse, T rappresenta il tipo di elemento, N rappresenta il numero di elementi ed è una costante non negativa in fase di compilazione.
[T]
Una vista con dimensioni dinamiche di una sequenza contigua, dove T rappresenta qualsiasi tipo.
stra
Affettatura di stringhe, utilizzata principalmente come riferimento, ovvero &str
(T, U,..)
Le successioni finite, T e U possono essere di diverso tipo.
fn(i32)->i32
Una funzione che riceve un parametro di tipo i32 e restituisce un parametro di tipo i32. Anche le funzioni hanno un tipo.
1.3.2 Dichiarazione di variabile e immutabilità
In Rust usiamo la parola chiave let per dichiarare le variabili. Dopo che una variabile è stata inizializzata, non è possibile assegnarle un altro valore. Se in seguito è necessario puntare la variabile su un'altra variabile (dello stesso tipo), è necessario precederla con la parola chiave mut.
1.3.3 Funzione
Le funzioni astraggono un insieme di istruzioni in entità denominate che possono successivamente essere chiamate da altro codice e aiutano gli utenti a gestire la complessità.
fn aggiungi(a: u64, b: u64) -> u64 { un b } fn principale() { sia a: u64 = 17; sia b = 3; lascia risultato = aggiungi(a, b); println!("Risultato {}", risultato); }
Le funzioni sono fondamentalmente espressioni che restituiscono un valore, che per impostazione predefinita è un valore di tipo () (unità), che è simile al tipo restituito void in C/C++.
1.3.4 Chiusura
La ruggine supporta le chiusure. Le chiusure sono simili alle funzioni ma contengono più informazioni sull'ambiente o sull'ambito in cui sono dichiarate. Mentre alle funzioni è associato un nome, le definizioni di chiusura no, ma possono essere assegnate a variabili. Un altro vantaggio dell'inferenza del tipo di Rust è che nella maggior parte dei casi è possibile specificare parametri per le chiusure senza tipi. Questa è la chiusura più semplice "let my_closure = ||();". Definiamo una chiusura senza parametri che non fa nulla. Possiamo quindi chiamarlo tramite my_closure(), che è simile a una funzione. Le due barre verticali "||" vengono utilizzate per memorizzare i parametri di chiusura, come |a, b|. A volte è necessario specificare il tipo del parametro (|a:u32|) quando Rust non riesce a capire il tipo corretto.
fn principale() { sia raddoppiatore = |x|. lascia valore = 5; let due volte = duplicatore(valore); println!("{} raddoppiato è {}", valore, due volte); lascia grande_chiusura = |b, c| { sia z = b c; z * due volte }; lascia che qualche_numero = big_closure(1, 2); println!("Risultato della chiusura: {}", some_number); }
1.3.5 Stringa
La stringa è uno dei tipi di dati più comunemente utilizzati in qualsiasi linguaggio di programmazione. In Rust, solitamente appaiono in due forme: tipo &str e tipo String. È garantito che le stringhe Rust siano sequenze di byte codificate UTF-8 valide. Non hanno la terminazione NULL come le stringhe C e possono contenere byte null tra le stringhe.
fn principale() { let domanda = "Come stai?"; let persona: String = "Bob".to_string(); let namaste = String::from("zd"); println!("{}! {} {}", namaste, domanda, persona); }
Nel codice precedente, il tipo di persona e namaste è String e il tipo di domanda è &str. Esistono molti modi per creare dati di tipo String. I dati di tipo stringa vengono allocati nell'heap. I dati di tipo &str sono solitamente un puntatore a una stringa esistente. Queste stringhe si trovano nello stack e nell'heap oppure possono essere stringhe nel segmento dati del codice oggetto compilato.
1.3.6 Condizioni e giudizi
I giudizi condizionali in Rust sono simili a quelli di altri linguaggi. Inoltre seguono una struttura tipo C if else.
fn principale() { lascia che ruggine_is_awesome = vero; se la ruggine_è_fantastica { println!("Certamente"); } altro { println!("Beh, dovresti provare Rust!"); } }
In Rust, il costrutto if non è un'istruzione, ma un'espressione. Nel linguaggio generale della programmazione, le istruzioni non restituiscono alcun valore, ma le espressioni sì. Questa distinzione significa che le condizioni if else in Rust restituiscono sempre un valore. Il valore può essere di tipo vuoto () o un valore effettivo. Qualunque sia l'ultima riga di parentesi graffe, diventa il valore restituito dell'espressione if else. È importante notare che i rami if e else dovrebbero avere lo stesso tipo di ritorno.
fn principale() { lascia risultato = se 1 == 2 { "Aspetta cosa?" } altro { "La ruggine ha un senso" }; println!("Sai una cosa? {}.", risultato); }
Quando il valore da assegnare viene restituito dall'espressione if else, dobbiamo utilizzare un punto e virgola come segno di fine. Ad esempio, se è un'espressione, allora let è un'istruzione che prevede la presenza di un punto e virgola alla fine.
1.3.7 corrispondenza espressione
Le espressioni di corrispondenza di Rust sono molto semplici e facili da usare. È fondamentalmente simile a una versione semplificata dell'istruzione switch in linguaggio C, che consente agli utenti di esprimere giudizi in base al valore della variabile e alla presenza o meno di funzionalità di filtro avanzate.
fn stato_req() -> u32 { 200 } fn principale() { lascia stato = req_status(); stato della corrispondenza { 200 => println!("Riuscito"), 404 => println!("Non trovato"), altro => { println!("Richiesta fallita con il codice: {}", other); } } }
Ogni corrispondenza deve restituire lo stesso tipo. Inoltre, dobbiamo eseguire una corrispondenza esatta su tutti i possibili valori di corrispondenza. Rust ci permette di ignorare le restanti possibilità utilizzando catch all variable (qui altro) o _ (underscore).
1.3.8 Ciclo
Fare qualcosa ripetutamente in Rust può essere realizzato utilizzando 3 costrutti, vale a dire loop, while e for. In tutti questi costrutti, di solito sono incluse le parole chiave continue e break, che consentono rispettivamente di saltare e di uscire dal ciclo.
fn principale() { sia mut x = 1024; ciclo continuo { se x < 0 { rottura; } println!("{} altre corse da fare", x); x-= 1; } }
Una caratteristica aggiuntiva dell'esecuzione dei cicli in Rust è la possibilità di etichettare i blocchi di codice del ciclo con nomi. Questo può essere utilizzato in situazioni in cui sono presenti due o più cicli annidati e si desidera interrompere uno qualsiasi di essi, non solo per i cicli che contengono direttamente istruzioni break.
fn stupido_sub(a: i32, b: i32) -> i32 { lascia che mut risultato = 0; 'incremento: ciclo { se risultato == a { sia mut dec = b; 'decremento: ciclo { ifdec==0{ break 'incremento; } altro { risultato -= 1; dicembre -= 1; } } } altro { risultato = 1; } } risultato } fn principale() { sia a = 10; sia b = 4; lascia risultato = silly_sub(a, b); println!("{} meno {} fa {}", a, b, risultato); }
Rust ha anche la parola chiave for, che è simile al ciclo for utilizzato in altri linguaggi, ma la sua implementazione è completamente diversa. Il ciclo for di Rust è fondamentalmente lo zucchero sintattico per un costrutto di iterazione più potente (iteratore). In poche parole, i cicli for in Rust funzionano solo con tipi che possono essere convertiti in iteratori. Uno di questi tipi è il tipo Range. Il tipo Intervallo può fare riferimento a una serie di numeri.
fn principale() { print!("Intervallo normale: "); per i in 0..10 { stampa!("{},", i); } stampaln!(); print!("Intervallo compreso: "); per i in 0..=10 { stampa!("(),", i); } }
1.3.9 Tipi di dati personalizzati
I tipi personalizzati sono tipi definiti dagli utenti. I tipi personalizzati possono essere composti da diversi tipi. Possono essere wrapper attorno a tipi primitivi o una combinazione di più tipi personalizzati. Sono disponibili in tre forme: struttura, enumerazione e unione, note anche come struct, enum e unione. Ti consentono di rappresentare i tuoi dati più facilmente. Le regole di denominazione per i tipi personalizzati seguono CamelCase.
Struttura
In Rust esistono tre forme di dichiarazione di struttura. La più semplice di queste è la unit struct, che viene dichiarata utilizzando la parola chiave struct, seguita dal suo nome e terminando con un punto e virgola.
struttura fittizia; fn principale() { lascia valore = fittizio; }
La seconda forma di struttura è la struttura tupla, a cui sono associati dati. A ciascuno di questi campi non viene assegnato un nome, ma viene fatto riferimento in base alla posizione nella definizione.
struttura Colore(u8, u8, u8); fn principale() { lascia bianco = Colore(255, 255, 255); sia rosso = bianco.0; sia verde = bianco.1; sia blu = bianco.2; println!("Valore rosso: {}", rosso); lascia arancione = Colore(255, 165, 0); lascia Colore(r, g, b) = arancione; println!("R: {}, G: {}, B: {} (arancione)", r, g, b); let Colore(r, _, b) = arancione; }
Le strutture di tupla sono ideali quando si modellano dati con meno di 5 attributi. Qualsiasi scelta diversa da questa ostacolerà la leggibilità e il ragionamento del codice. Per i tipi di dati con più di 3 campi, costruire strutture utilizzando un linguaggio simile al C. Questa è la terza forma e la forma più comunemente utilizzata.
struttura Giocatore { nome: stringa, iq: u8, amici: u8, punteggio: u16 } fn bump_player_score(mut giocatore: Giocatore, punteggio: u16) { player.score = punteggio; println!("Statistiche giocatore aggiornate:"); } fn principale() { let nome = "Alice".to_string(); let giocatore = Giocatore { nome, iq: 171, amici: 134, punteggio: 1129 }; bump_player_score(giocatore, 120); }
enumerare
Le enumerazioni sono un buon modo per farlo quando è necessario modellare diversi tipi di cose. Viene creato utilizzando la parola chiave enum, seguita dal nome dell'enumerazione e da una coppia di parentesi graffe. All'interno delle parentesi graffe possiamo scrivere tutti i tipi possibili, cioè le varianti. Queste varianti possono essere definite con o senza dati e i dati contenuti possono essere qualsiasi tipo far, struttura, struttura tupla o anche un tipo di enumerazione.
enum Direzione { N, E, S, W } enumAzione giocatore { Mossa { direzione: direzione, Velocità: u8 }, Aspettare, Attacco (direzione) } fn principale() { let simulated_player_action = PlayerAction::Move { direzione: Direzione::N, velocità: 2, }; corrisponde a simulazione_giocatore_azione { PlayerAction::Wait => println!("Il giocatore vuole aspettare"), PlayerAction::Move { direzione, velocità } => { println!("Il giocatore vuole muoversi nella direzione {:?} con velocità {}", direzione, velocità) } Azione giocatore::Attacco(direzione) => { println!("Il giocatore vuole attaccare la direzione {:?}", direzione) } }; }
1.3.10 Funzioni e metodi sui tipi
blocco impl su struct
Possiamo aggiungere un comportamento a una struttura definita utilizzando due meccanismi: funzioni di tipo costruttore e metodi getter e setter.
struttura Giocatore { nome: stringa, iq: u8, amici: u8 } Giocatore implicito { fn with_name(nome: &str) -> Giocatore { Giocatore { nome: nome.to_string(), quoziente d'intelligenza: 100, amici: 100 } } fn trova_amici(&self) -> u8 { sé.amici } fn imposta amici(&mut self, count: u8) { self.amici = conta; } } fn principale() { let mut giocatore = Giocatore::con_nome("Dave"); giocatore.set_friends(23); println!("Gli amici di {} contano: {}", player.name, player.get_friends()); let _ = Giocatore::get_friends(&giocatore); }
Metodo associato: questo metodo non ha il tipo self come primo parametro. È simile ai metodi statici nei linguaggi di programmazione orientati agli oggetti. Questi metodi possono essere richiamati sul tipo stesso e non richiedono la chiamata di un'istanza del tipo. Un metodo associato viene chiamato facendo precedere il nome del metodo dal nome della struttura e dai due punti doppi.
Metodo di istanza: una funzione che accetta self come primo parametro esterno. Il self qui è simile al self in Python e punta all'istanza che implementa il metodo.
blocchi ed enumerazioni impl
Le enumerazioni sono ampiamente utilizzate nelle macchine a stati e, se utilizzate con espressioni di corrispondenza, possono rendere il codice di transizione dello stato molto conciso. Possono essere utilizzati anche per la modellazione di tipi di errore personalizzati.
enumModalitàPagamento { Addebito, Credito, PayPal } fn pagamento_con_credito(amt: u64) { println!("Elaborazione del pagamento del credito di {}", amt); } fn pagamento_per_debito(amt: u64) { println!("Elaborazione pagamento addebito di {}", amt); } fn reindirizzamento_paypal(amt: u64) { println!("Reindirizzamento a PayPal per importo: {}", amt); } modalità di pagamento impl { fn paga(&auto, importo: u64) { abbinare se stesso { ModalitàPagamento::Debito => pagamento_per_debito(importo), ModalitàPagamento::Credito => pagamento_con_credito(importo), ModalitàPagamento::Paypal => paypal_redirect(importo) } } } fn get_saved_payment_mode() -> ModalitàPagamento { Modalità di pagamento::Addebito } fn principale() { let payment_mode = get_saved_payment_mode(); modalità_pagamento.pay(512); }
Modulo 1.3.11, istruzioni di importazione e utilizzo
I linguaggi di programmazione spesso forniscono un modo per dividere grandi blocchi di codice in più file per gestire la complessità. Java segue la convenzione secondo cui ogni file .java è una classe pubblica e C fornisce file di intestazione e istruzioni include. Rust fornisce un meccanismo di modulo. I moduli sono un modo per denominare e organizzare il codice nei programmi Rust.
Ogni programma Rust richiede un modulo root. Per i file eseguibili, di solito è il file main.rs, mentre per le librerie è solitamente il file lib.rs.
I moduli possono essere dichiarati all'interno di altri moduli o organizzati in file e directory.
Affinché il compilatore riconosca il nostro modulo, dobbiamo usare la parola chiave mod dichiarazione. Nel nostro modulo root, dobbiamo usare la parola chiave use prima del nome del modulo, il che significa portare l'elemento nell'ambito.
Gli elementi definiti in un modulo sono privati per impostazione predefinita e devono essere esposti ai chiamanti utilizzando la parola chiave pub.
1.3.12 Raccolta
vettore
Gli array hanno una lunghezza fissa e possono memorizzare elementi dello stesso tipo. Sono rappresentati da [T, N], dove T rappresenta qualsiasi tipo e N rappresenta il numero di elementi dell'array. La dimensione dell'array non può essere rappresentata da una variabile e deve essere un valore letterale di usize.
tupla
Elenco progetti
coppia chiave/valore
fetta
1.3.13 Iteratore
sottoargomento
sottoargomento
sottoargomento
1.4 Migliora il contatore dei personaggi
1.5 Riepilogo
Capitolo 2 Utilizzo di Cargo per gestire progetti
2.1 Gestore dei pacchetti software
2.2 Moduli
2.2.1 Moduli annidati
2.2.2 Utilizzo di file come moduli
2.2.3 Usare le directory come moduli
2.3 Cargo e biblioteche
2.3.1 Creare un nuovo progetto Cargo
2.3.2 Carico e dipendenze
2.3.3 Utilizzo di Cargo per eseguire test
2.3.4 Utilizzo di Cargo per eseguire l'esempio
2.3.5 Area di lavoro del carico
2.4 Estensione dello strumento di carico
2.4.1 Sottocomandi e installazione di Cargo
2.4.2 Utilizzare clippy per formattare il codice
2.4.3 Introduzione al file manifest Cargo.toml
2.5 Configurare un ambiente di sviluppo Rust
2.6 Utilizzare Cargo per creare il programma imgtool
2.7 Riepilogo
Capitolo 3 Test, documentazione e benchmarking
3.1 Scopo del test
3.2 Organizzazione delle prove
3.3 Test unitari
3.3.1 Il primo test unitario
3.3.2 Esecuzione di test
3.3.3 Isolare il codice di test
3.3.4 Test di fallimento
3..3.5 Ignorare i test
3.4 Test di integrazione
3.4.1 Primo test di integrazione
3.4.2 Condivisione di codice comune
3.5 Documentazione
3.5.1 Scrivere la documentazione
3.5.2 Generare e visualizzare documenti
3.5.3 Documenti ospitati
3.5.4 Proprietà del documento
3.5.5 Test documentati
3.6 Riferimento
3.6.1 Strumenti di micro-benchmark integrati
3.6.2 Benchmarking sulla versione stabile di Rust
3.7 Scrittura e test di pacchetti software - simulatore di porte logiche
3.8 Test di integrazione CI e Travis CI
3.9 Riepilogo
Capitolo 4 Tipi, generici e tratti
4.1 Sistemi di tipi e loro importanza
4.2 Generici
4.2.1 Creazione di farmaci generici#
4.2.2 Implementazione generica
4.2.3 Applicazioni generiche
4.3 Usare le caratteristiche per astrarre il comportamento
4.3.1 Caratteristiche
4.3.2 Varie forme di funzionalità
4.4 Utilizzo delle funzionalità generiche del pacchetto: intervalli di funzionalità
4.4.1 Intervalli caratteristici sui tipi
4.4.2 Intervalli caratteristici su funzioni generiche e blocchi di codice impl
4.4.3 Utilizzare la combinazione di funzioni " " per formare un intervallo
4.4.4 Intervallo di funzionalità e sintassi delle funzionalità impl
4.5 Introduzione alle funzionalità della libreria standard
4.6 Usare oggetti tratto per ottenere un vero polimorfismo
4.6.1 Distribuzione
4.6.2 Oggetti caratteristici
4.7 Riepilogo
Capitolo 5 Gestione e sicurezza della memoria
5.1 Programmi e memoria
5.2 Come i programmi utilizzano la memoria
5.3 Gestione e classificazione della memoria
5.4 Introduzione all'allocazione della memoria
5.4.1 Pila
5.4.2 Mucchio
5.5 Difetti nella gestione della memoria
5.6 Sicurezza della memoria
5.7 Tre principi di sicurezza della memoria
5.7.1 Proprietà
5.7.2 Riutilizzo dei tipi attraverso i tratti
5.7.3 Prestito
5.7.4 Tipi di metodi basati sulle regole di prestito
5.7.5 Ciclo di vita
5.8 Tipi di puntatori in Rust
5.8.1 Riferimenti: puntatori sicuri
5.8.2 Puntatori grezzi
5.8.3 Puntatori intelligenti
5.8.4 Puntatori intelligenti con conteggio dei riferimenti
5.8.5 Applicazione della variabilità interna
5.9 Riepilogo
Capitolo 6 Gestione delle eccezioni
6.1 Introduzione alla gestione delle eccezioni
6.2 Eccezioni recuperabili
6.2.1 Opzione
6.2.2 Risultato
6.3 Combinazione Opzione/Risultato
6.3.1 Combinatori comuni
6.3.2 Applicazione combinatore
6.3.3 Conversione tra tipi di Opzione e Risultato
6.4 Restituzione anticipata e operatore "?"
6.5 Eccezioni irrecuperabili
6.6 Errori personalizzati e caratteristiche degli errori
6.7 Riepilogo
Capitolo 7 Concetti avanzati
7.1 Introduzione ai sistemi di tipi
7.1.1 Blocchi di codice ed espressioni
7.1.2 dichiarazione let
7.1.3 Cicli come espressioni
7.1.4 Chiarezza dei tipi e distinzione dei simboli nei tipi numerici
7.1.5 Inferenza del tipo
7.1.6 Alias di tipo
7.2 Corda
7.2.1 Stringa contenente la proprietà - Stringa
7.2.2 Stringa in prestito——&str
7.2.3 Affettamento e spezzettamento di stringhe
7.2.4 Utilizzo delle stringhe nelle funzioni
7.2.5 Concatenazione di stringhe
7.2.6 Scenari applicativi di &str e String
7.3 Valori globali
7.3.1 Costanti
7.3.2 Valori statici
7.3.3 Funzione in fase di compilazione——const fn
7.3.4 Valori statici dinamici tramite macro lazy_static
7.4 Iteratori
7.5 Tipi avanzati
7.5.1 Tipi di lunghezza indefinita
7.5.2 Tipi di funzioni
7.5.3 non digitare mai “!” e inviare la funzione
7.5.4 Unione
7.5.5 Mucca
7.6 Funzionalità avanzate
7.6.1 Dimensionato e ?Dimensionato
7.6.2 Prestito e AsRef
7.6.3 ToBoned
7.6.4 Da e dentro
7.6.5 Oggetti caratteristici e sicurezza degli oggetti
7.6.6 Sintassi generale della chiamata di funzione
7.6.7 Regole di funzionalità
7.7 Chiusure anticipate
7.7.1 Chiusura Fn
7.7.2 Chiusura FnMut
7.7.3 Chiusura FnOnce
7.8 Costanti in strutture, enumerazioni e tratti
7.9 Moduli, percorsi e importazioni
7.9.1 Importa
7.9.2 Importare nuovamente
7.9.3 Privacy
7.10 Schemi di abbinamento avanzati e protezioni
7.10.1 Guardia di Gara
7.10.2 Costruzione di locazioni avanzate
7.11 Lancio
7.12 Tipi e memoria
7.12.1 Allineamento della memoria
7.12.2 modulo std::mem
7.13 Serializzazione e deserializzazione mediante serde
7.14 Riepilogo
Capitolo 8 Concorrenza
8.1 Modello di esecuzione del programma
8.2 Concorrenza
8.2.1 Metodi simultanei
8.2.2 Difetti
8.3 Concorrenza in Rust
8.3.1 Nozioni di base sui thread
8.3.2 Discussioni personalizzate
8.3.3 Accesso ai dati nei thread
8.4 Modello di concorrenza dei thread
8.4.1 Modello di condivisione degli Stati
8.4.2 Mutua esclusione
8.4.3 Mutabilità condivisa attraverso Arc e Mutex
8.4.4 Comunicazione tramite messaggistica
8.5 Sicurezza del filo in Rust
8.5.1 Cos'è la sicurezza del thread?
8.5.2 Caratteristiche di sicurezza del filo
8.5.3 Invia
8.5.4 Sincronizzazione
8.6 Implementare la concorrenza utilizzando il modello ad attori
8.7 Altre biblioteche
8.8 Riepilogo
Capitolo 9 Macro e metaprogrammazione
9.1 Cos’è la metaprogrammazione?
9.2 Scenari applicativi delle macro di Rust
9.3 Macro e loro tipi in Rust
9.4 Crea macro utilizzando macro_rules!
9.5 Macro integrate nella libreria standard
9.6 macro_rules! Tipo di tag macro
9.7 Ripetizione nelle macro
9.8 Applicazione avanzata di macro: scrittura DSL per l'inizializzazione HashMap
9.9 Macro casi d'uso - test di scrittura
9.10 Esercizio
9.11 Macro di processo
9.12 Macro derivate
9.13 Macro di alto livello
9.14 Pacchetti software di macro di processo di uso comune
9.15 Riepilogo
Capitolo 10 Rust non sicuro e interfacce di funzioni esterne
10.1 Sicurezza e pericolo
10.1.1 Funzioni non sicure e blocchi di codice
10.1.2 Caratteristiche e implementazioni non sicure
10.2 Chiamare il codice C in Rust
10.3 Chiamare il codice Rust tramite il linguaggio C
10.4 Usare librerie C/C esterne in Rust
10.5 Costruire estensioni Python native utilizzando PyO3
10.6 Creazione di estensioni native per Node.js in Rust
10.7 Riepilogo
Capitolo 11 Registro
11.1 La registrazione e la sua importanza
11.2 Requisiti per un framework di logging
11.3 Framework di registrazione e sue caratteristiche
11.4 Metodo di registrazione
11.4.1 Registrazione non strutturata
11.4.2 Registrazione strutturata
11.5 Accedere a Rust
11.5.1 log—Registrazione per Rust
11.5.2 env_logger
11.5.3 log4rs
11.5.4 Utilizzo di slog per la registrazione strutturata
11.6 Riepilogo
Capitolo 12 Rust e programmazione di rete
12.1 Introduzione alla programmazione di rete
12.2 I/O di rete sincrona
12.3 I/O di rete asincrona
12.3.1 Astrazioni asincrone in Rust
12.3.2 Creazione di un server Redis asincrono
12.4 Riepilogo
Capitolo 13 Creazione di applicazioni Web con Rust
13.1 Applicazioni Web in Rust
13.2 Utilizzo di hyper per la comunicazione HTTP
13.2.1 L'API lato server Hyper crea un servizio URL breve
13.2.2 Hyper come client: creazione di un client URL breve
13.2.3 Struttura web
13.3 Conoscenze di base di Actix-web
13.4 Creazione di un'API di segnalibri utilizzando actix-web
13.5 Riepilogo
Capitolo 14 Rust e WebAssembly
14.1 L'importanza della durabilità dei dati
14.2SQLite
14.3 PostgreSQL
14.4 Pool di connessioni r2d2
14.5 Postgres e diesel ORM
14.6 Riepilogo
Capitolo 15 Rust e WebAssembly
15.1 Cos'è WebAsmbly
15.2 Obiettivi di progettazione di WebAssembly
15.3 Iniziare con WebAssembly
15.3.1 Prova in linea
15.3.2 Metodi per generare WebAssembly
15.4 Rust e WebAssembly
15.4.1 wasm-bindgen
15.4.2 Altri progetti WebAssembly
15.5 Riepilogo
Capitolo 16 Rust e applicazioni desktop
16.1 Introduzione allo sviluppo della GUI
16.2 Quadro GTK
16.3 Costruire un'applicazione desktop per le notizie tramite gtk-rs
16.4 Esercizi
16.5 Altri framework UI emergenti
16.6 Riepilogo
Capitolo 17 Debug
17.1 Introduzione al debug
17.1.1 Nozioni di base sul debugger
17.1.2 Prerequisiti per la messa in servizio
17.1.3 Configurazione GDB
17.1.4 Un programma di esempio: buggie
17.1.5 Nozioni di base sul GDB
17.1.6 Integrazione di GDB nel codice di Visual Studio
17.2 Introduzione al debugger rr
17.3 Riepilogo