programmazione:rust:appunti_sparsi
Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
| Entrambe le parti precedenti la revisioneRevisione precedenteProssima revisione | Revisione precedente | ||
| programmazione:rust:appunti_sparsi [08/04/2026 11:33] – Fabio Di Matteo | programmazione:rust:appunti_sparsi [30/05/2026 15:51] (versione attuale) – [Funzioni async con tokio] Fabio Di Matteo | ||
|---|---|---|---|
| Linea 2: | Linea 2: | ||
| Autore: **//Fabio Di Matteo//** \\ Ultima revisione: | Autore: **//Fabio Di Matteo//** \\ Ultima revisione: | ||
| - | Provenendo da altri linguaggi ho avuto qualche difficoltà ad abituarmi alla sintassi e buone pratiche incoraggiate dal Rust. Metto qualche appunto. | + | Provenendo da altri linguaggi ho avuto qualche difficoltà ad abituarmi alla sintassi e buone pratiche incoraggiate dal Rust. Metto qualche appunto. |
| + | |||
| + | ===== Libri ===== | ||
| + | [[https:// | ||
| + | [[https:// | ||
| ===== Blocco try/catch ===== | ===== Blocco try/catch ===== | ||
| Linea 60: | Linea 64: | ||
| } | } | ||
| </ | </ | ||
| + | < | ||
| + | </ | ||
| Linea 87: | Linea 92: | ||
| </ | </ | ||
| - | N.B. **.into()** In poche parole prende un valore di un tipo e lo converte in un altro tipo, se esiste una conversione definita (tramite i trait From/ | + | |
| ==== Con un semplice if ==== | ==== Con un semplice if ==== | ||
| Linea 160: | Linea 164: | ||
| assicurandoci prima di aver installato il target in sopraindicato. | assicurandoci prima di aver installato il target in sopraindicato. | ||
| + | |||
| + | ===== Le classi ===== | ||
| + | Un esempio minimo. | ||
| + | <code rust> | ||
| + | struct Persona { | ||
| + | id: i16, | ||
| + | name: String, | ||
| + | surname: String, | ||
| + | } | ||
| + | |||
| + | impl Persona { | ||
| + | fn new() -> Self { | ||
| + | return Self { | ||
| + | id: 0, | ||
| + | name: "" | ||
| + | surname: "" | ||
| + | }; | ||
| + | } | ||
| + | fn set(& | ||
| + | self.id = id; | ||
| + | self.name = name; | ||
| + | self.surname = surname; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fn main() { | ||
| + | let mut p = Persona:: | ||
| + | p.set(1, " | ||
| + | |||
| + | println!(" | ||
| + | } | ||
| + | |||
| + | |||
| + | </ | ||
| + | Versione con l' | ||
| + | |||
| + | <code rust> | ||
| + | struct Persona { | ||
| + | id: i16, | ||
| + | name: String, | ||
| + | surname: String, | ||
| + | } | ||
| + | |||
| + | impl Persona { | ||
| + | fn new() -> Self { | ||
| + | return Self { | ||
| + | id: 0, | ||
| + | name: "" | ||
| + | surname: "" | ||
| + | }; | ||
| + | } | ||
| + | fn set(& | ||
| + | self.id = id; | ||
| + | self.name = name; | ||
| + | self.surname = surname; | ||
| + | } | ||
| + | |||
| + | fn get(& | ||
| + | if op == " | ||
| + | return self.name.clone(); | ||
| + | } else if op == " | ||
| + | return self.surname.clone(); | ||
| + | } else { | ||
| + | return self.id.to_string(); | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fn main() { | ||
| + | let mut p = Persona:: | ||
| + | p.set(1, " | ||
| + | let nome = p.get(" | ||
| + | let cognome = p.get(" | ||
| + | let id = p.get(" | ||
| + | |||
| + | println!(" | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | ===== Sviluppo di programmi dotatati di gui ===== | ||
| + | Di seguito le mmie esperienze: | ||
| + | |||
| + | * [[programmazione: | ||
| + | * [[programmazione: | ||
| + | * [[https:// | ||
| + | |||
| + | ===== I thread ===== | ||
| + | thread:: | ||
| + | |||
| + | <code Rust> | ||
| + | let t = thread:: | ||
| + | for i in 1..100 { | ||
| + | println!(" | ||
| + | thread:: | ||
| + | } | ||
| + | }); | ||
| + | |||
| + | </ | ||
| + | |||
| + | Aspettare la fine del thread: | ||
| + | <code rust> | ||
| + | t.join().unwrap(); | ||
| + | |||
| + | </ | ||
| + | |||
| + | Condivide valori tra thread tramite riferimento grazie ad Arc: | ||
| + | <code rust> | ||
| + | use std:: | ||
| + | use std:: | ||
| + | |||
| + | let value = Arc:: | ||
| + | let v1 = Arc:: | ||
| + | let handle = thread:: | ||
| + | println!(" | ||
| + | }); | ||
| + | println!(" | ||
| + | handle.join().unwrap(); | ||
| + | |||
| + | </ | ||
| + | |||
| + | La condivisione è sicura. Potremmo anche condividere **mpsc:: | ||
| + | |||
| + | |||
| + | ===== Funzioni async con tokio ===== | ||
| + | Eseguire funzioni che richiedono tempo con il runtime tokio: | ||
| + | <code rust> | ||
| + | use tokio:: | ||
| + | |||
| + | async fn asincrona() { | ||
| + | sleep(Duration:: | ||
| + | println!(" | ||
| + | } | ||
| + | |||
| + | # | ||
| + | async fn main() { | ||
| + | // Avvio una funzione async con tokio e passo il controllo | ||
| + | // alle istruzioni successive | ||
| + | tokio:: | ||
| + | |||
| + | println!(" | ||
| + | sleep(Duration:: | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | Aspettiamo che una funzione, | ||
| + | |||
| + | <code rust> | ||
| + | use tokio:: | ||
| + | |||
| + | async fn asincrona() -> i32 { | ||
| + | sleep(Duration:: | ||
| + | println!(" | ||
| + | return 6000; | ||
| + | } | ||
| + | |||
| + | # | ||
| + | async fn main() { | ||
| + | // Avvio una funzione async con tokio e passo il controllo | ||
| + | // alle istruzioni successive. | ||
| + | let r = tokio:: | ||
| + | |||
| + | // Scrivo qualcosa dal main e dopo un secondo il programma dovrebbe terminare | ||
| + | // Invece no! Aspetto il valore di " | ||
| + | // r.await | ||
| + | println!(" | ||
| + | sleep(Duration:: | ||
| + | |||
| + | // Ora che il valore di " | ||
| + | // oppure stampo " | ||
| + | println!( | ||
| + | "Ho aspettato il valore di r {}", | ||
| + | r.await.unwrap_or_else(|_| 0) | ||
| + | ); | ||
| + | } | ||
| + | |||
| + | |||
| + | </ | ||
| + | |||
| + | ===== Comunicare con le funzioni async ===== | ||
| + | <code rust> | ||
| + | use std:: | ||
| + | use tokio:: | ||
| + | |||
| + | async fn asincrona(t: | ||
| + | loop { | ||
| + | t.send(" | ||
| + | sleep(Duration:: | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # | ||
| + | async fn main() { | ||
| + | let (tx, rx) = mpsc:: | ||
| + | |||
| + | let tx_clone = tx.clone(); | ||
| + | tokio:: | ||
| + | |||
| + | // Un loop che riceve messaggi dalla funzione asincrona e | ||
| + | // li stampa a video. | ||
| + | loop { | ||
| + | sleep(Duration:: | ||
| + | let val = rx.recv().unwrap_or_else(|_| " | ||
| + | println!(" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ===== Websocket ===== | ||
| + | Un piccolo esempio di server websocket che aspetta un pacchetto json e lo elabora. Ecco la struttura del json: | ||
| + | |||
| + | <code json> | ||
| + | {" | ||
| + | </ | ||
| + | |||
| + | <code rust> | ||
| + | use std:: | ||
| + | use std:: | ||
| + | use tungstenite:: | ||
| + | use serde:: | ||
| + | use serde_json:: | ||
| + | //use serde_json:: | ||
| + | |||
| + | |||
| + | # | ||
| + | struct Action{ | ||
| + | name : String, | ||
| + | params: String, | ||
| + | } | ||
| + | |||
| + | |||
| + | fn parse_json(json_str: | ||
| + | serde_json:: | ||
| + | } | ||
| + | |||
| + | |||
| + | fn handle(j: String) -> String { | ||
| + | |||
| + | let a : Action; | ||
| + | if let Err(a) = parse_json(j.as_str()) { | ||
| + | drop(a); | ||
| + | " | ||
| + | } else { | ||
| + | a=parse_json(j.as_str()).unwrap(); | ||
| + | |||
| + | //For example return my " | ||
| + | a.name | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fn main() { | ||
| + | let server = TcpListener:: | ||
| + | for stream in server.incoming() { | ||
| + | spawn(move || { | ||
| + | let mut websocket = accept(stream.unwrap()).unwrap(); | ||
| + | loop { | ||
| + | if let Ok(msg) = websocket.read(){ | ||
| + | if msg.is_binary() || msg.is_text() { | ||
| + | |||
| + | if let Err(e) = websocket.send(handle(msg.to_string()).into()){ | ||
| + | eprintln!(" | ||
| + | drop(e); | ||
| + | } | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | | ||
| + | } | ||
| + | }); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | **Cargo.toml** | ||
| + | <code toml> | ||
| + | [package] | ||
| + | name = " | ||
| + | version = " | ||
| + | edition = " | ||
| + | |||
| + | [dependencies] | ||
| + | tungstenite = " | ||
| + | serde = { version = " | ||
| + | serde_json = " | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Ottenere directory eseguibile ===== | ||
| + | <code rust> | ||
| + | use std::{env, io, path:: | ||
| + | |||
| + | fn exe_dir() -> Result< | ||
| + | let exe = env:: | ||
| + | match exe.parent() { | ||
| + | Some(p) => Ok(p.to_path_buf()), | ||
| + | None => Err(io:: | ||
| + | io:: | ||
| + | "no parent directory for executable", | ||
| + | )), | ||
| + | } | ||
| + | } | ||
| + | |||
| + | fn main() { | ||
| + | // Utilizzarla senza controllo errori così: | ||
| + | // let myexe_path = exe_dir(); | ||
| + | // println!( | ||
| + | // " | ||
| + | // | ||
| + | // ); | ||
| + | |||
| + | let myexe_path = exe_dir(); | ||
| + | match myexe_path { | ||
| + | Ok(p) => { | ||
| + | println!( | ||
| + | "Il percorso del mio eseguibile è {}", | ||
| + | p.display().to_string() | ||
| + | ); | ||
| + | } | ||
| + | Err(e) => { | ||
| + | eprintln!(" | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </ | ||
programmazione/rust/appunti_sparsi.1775640806.txt.gz · Ultima modifica: 08/04/2026 11:33 da Fabio Di Matteo
