Mindmap-Galerie Mastering RUST 2. Auflage
Dies ist eine Mindmap zum Beherrschen von RUST. Durch die oben genannten Schritte und Vorschläge können Sie Ihre Rust-Programmierkenntnisse schrittweise verbessern und die Speichersicherheit und effiziente Leistung von Rust genießen.
Bearbeitet um 2024-04-04 15:14:48Einhundert Jahre Einsamkeit ist das Meisterwerk von Gabriel Garcia Marquez. Die Lektüre dieses Buches beginnt mit der Klärung der Beziehungen zwischen den Figuren. Im Mittelpunkt steht die Familie Buendía, deren Wohlstand und Niedergang, interne Beziehungen und politische Kämpfe, Selbstvermischung und Wiedergeburt im Laufe von hundert Jahren erzählt werden.
Einhundert Jahre Einsamkeit ist das Meisterwerk von Gabriel Garcia Marquez. Die Lektüre dieses Buches beginnt mit der Klärung der Beziehungen zwischen den Figuren. Im Mittelpunkt steht die Familie Buendía, deren Wohlstand und Niedergang, interne Beziehungen und politische Kämpfe, Selbstvermischung und Wiedergeburt im Laufe von hundert Jahren erzählt werden.
Projektmanagement ist der Prozess der Anwendung von Fachwissen, Fähigkeiten, Werkzeugen und Methoden auf die Projektaktivitäten, so dass das Projekt die festgelegten Anforderungen und Erwartungen im Rahmen der begrenzten Ressourcen erreichen oder übertreffen kann. Dieses Diagramm bietet einen umfassenden Überblick über die 8 Komponenten des Projektmanagementprozesses und kann als generische Vorlage verwendet werden.
Einhundert Jahre Einsamkeit ist das Meisterwerk von Gabriel Garcia Marquez. Die Lektüre dieses Buches beginnt mit der Klärung der Beziehungen zwischen den Figuren. Im Mittelpunkt steht die Familie Buendía, deren Wohlstand und Niedergang, interne Beziehungen und politische Kämpfe, Selbstvermischung und Wiedergeburt im Laufe von hundert Jahren erzählt werden.
Einhundert Jahre Einsamkeit ist das Meisterwerk von Gabriel Garcia Marquez. Die Lektüre dieses Buches beginnt mit der Klärung der Beziehungen zwischen den Figuren. Im Mittelpunkt steht die Familie Buendía, deren Wohlstand und Niedergang, interne Beziehungen und politische Kämpfe, Selbstvermischung und Wiedergeburt im Laufe von hundert Jahren erzählt werden.
Projektmanagement ist der Prozess der Anwendung von Fachwissen, Fähigkeiten, Werkzeugen und Methoden auf die Projektaktivitäten, so dass das Projekt die festgelegten Anforderungen und Erwartungen im Rahmen der begrenzten Ressourcen erreichen oder übertreffen kann. Dieses Diagramm bietet einen umfassenden Überblick über die 8 Komponenten des Projektmanagementprozesses und kann als generische Vorlage verwendet werden.
Beherrscht Rost
Kapitel 1 Erste Schritte mit Rust
1.1 Was ist Rust und warum brauchen Sie es?
Rust ist eine schnelle, hochgradig gleichzeitige, sichere und leistungsstarke Programmiersprache, die ursprünglich 2006 von Graydon Hoare erstellt und veröffentlicht wurde. Mittlerweile ist es eine Open-Source-Sprache, die hauptsächlich vom Mozilla-Team und vielen Mitgliedern der Open-Source-Community gepflegt und entwickelt wird.
Rust verfügt über eine Open-Source-Entwicklungswebsite auf GitHub und die Entwicklungsdynamik ist sehr schnell. Neue Funktionen werden der Sprache durch einen von der Community gesteuerten RFC-Prozess (Request For Comment) hinzugefügt, bei dem jeder neue Funktionen einreichen und diese dann in einem RFC-Dokument detailliert beschreiben kann. Anschließend wird ein Konsens über den RFC angestrebt, und wenn ein Konsens erzielt wird, tritt die Funktion in die Implementierungsphase ein.
Rust existiert als statische und stark typisierte Sprache. Statische Attribute bedeuten, dass der Compiler zur Kompilierungszeit über Informationen zu allen relevanten Variablen und Typen verfügt und zur Kompilierungszeit viele Prüfungen durchführt, so dass zur Laufzeit nur ein kleiner Teil der Typprüfung verbleibt.
1.2 Installieren Sie die Rust-Werkzeugkette
rustup.rs
1.3 Einführung in Rust
1.3.1 Primitive Typen
bool
Dies sind gängige boolesche Werte, die entweder wahr oder falsch sein können.
verkohlen
Charakter
ganze Zahl
Dieser Typ zeichnet sich durch die Bitbreite aus. Die von Rust unterstützte maximale Länge beträgt 128 Bit.
Größe
Eine vorzeichenbehaftete Ganzzahl variabler Größe (Größe hängt von der Größe des zugrunde liegenden Zeigers ab).
nutzen
Ganzzahl ohne Vorzeichen variabler Größe (Größe hängt von der Größe des zugrunde liegenden Zeigers ab).
f32
f32-Bit-Gleitkommatyp
f64
f64-Bit-Gleitkommatyp
[T; N]
Bei einem Array fester Größe stellt T den Elementtyp dar, N stellt die Anzahl der Elemente dar und ist zur Kompilierungszeit eine nicht negative Konstante.
[T]
Eine dynamisch dimensionierte Ansicht einer zusammenhängenden Sequenz, wobei T einen beliebigen Typ darstellt.
str
String-Slicing, hauptsächlich als Referenz verwendet, d. h. &str
(T, U, ..)
Endliche Folgen T und U können unterschiedlicher Art sein.
fn(i32)->i32
Eine Funktion, die einen Parameter vom Typ i32 empfängt und einen Parameter vom Typ i32 zurückgibt. Funktionen haben auch einen Typ.
1.3.2 Variablendeklaration und Unveränderlichkeit
In Rust verwenden wir das Schlüsselwort let, um Variablen zu deklarieren. Nachdem eine Variable initialisiert wurde, kann ihr kein weiterer Wert zugewiesen werden. Wenn Sie die Variable später auf eine andere Variable (des gleichen Typs) verweisen müssen, müssen Sie ihr das Schlüsselwort mut voranstellen.
1.3.3 Funktion
Funktionen abstrahieren eine Reihe von Anweisungen in benannte Entitäten, die später von anderem Code aufgerufen werden können und Benutzern helfen, die Komplexität zu verwalten.
fn add(a: u64, b: u64) -> u64 { ein b } fn main() { sei a: u64 = 17; sei b = 3; let result = add(a, b); println!("Ergebnis {}", Ergebnis); }
Funktionen sind im Grunde Ausdrücke, die einen Wert zurückgeben, der standardmäßig ein Wert vom Typ () (Einheit) ist, der dem Rückgabetyp void in C/C++ ähnelt.
1.3.4 Schließung
Rust unterstützt Schließungen. Abschlüsse ähneln Funktionen, verfügen jedoch über mehr Informationen über die Umgebung oder den Bereich, in dem sie deklariert werden. Während mit Funktionen ein Name verknüpft ist, ist dies bei den Definitionen von Abschlüssen nicht der Fall, sie können jedoch Variablen zugewiesen werden. Ein weiterer Vorteil der Rust-Typinferenz besteht darin, dass Sie in den meisten Fällen Parameter für Abschlüsse ohne Typen angeben können. Dies ist der einfachste Abschluss „let my_closure = ||();“. Wir definieren einen parameterlosen Abschluss, der nichts tut. Wir können es dann über my_closure() aufrufen, was einer Funktion ähnelt. Die beiden vertikalen Balken „||“ werden zum Speichern von Abschlussparametern wie |a, b| verwendet. Manchmal ist es notwendig, den Parametertyp (|a:u32|) anzugeben, wenn Rust den richtigen Typ nicht herausfinden kann.
fn main() { sei doubler = |x|. sei Wert = 5; let two = doubler(value); println!("{} doubled is {}", value, double); let big_closure = |b, c| {. sei z = b c; z * zweimal }; let some_number = big_closure(1, 2); println!("Ergebnis aus Abschluss: {}", some_number); }
1.3.5 Zeichenfolge
String ist einer der am häufigsten verwendeten Datentypen in jeder Programmiersprache. In Rust erscheinen sie normalerweise in zwei Formen: &str-Typ und String-Typ. Bei Rust-Strings handelt es sich garantiert um gültige UTF-8-codierte Bytesequenzen. Sie sind nicht NULL-terminiert wie C-Strings und können Null-Bytes zwischen Strings enthalten.
fn main() { let question = „Wie geht es dir?“; let person: String = "Bob".to_string(); let namaste = String::from("zd"); println!("{}! {} {}", namaste, Frage, Person); }
Im obigen Code ist der Typ „Person“ und „Namaste“ „String“ und der Typ der Frage ist „&str“. Es gibt viele Möglichkeiten, Daten vom Typ String zu erstellen. Daten vom Typ „String“ werden in der Regel als Zeiger auf eine vorhandene Zeichenfolge im Stapel und im Heap gespeichert. Sie können aber auch Zeichenfolgen im Datensegment des kompilierten Objektcodes sein.
1.3.6 Bedingungen und Urteile
Bedingte Urteile in Rust ähneln denen in anderen Sprachen. Sie folgen auch einer C-ähnlichen if else-Struktur.
fn main() { let rust_is_awesome = true; if rust_is_awesome { println!("In der Tat"); } anders { println!("Nun, Sie sollten Rust ausprobieren!"); } }
In Rust ist das if-Konstrukt keine Anweisung, sondern ein Ausdruck. Im allgemeinen Programmierjargon geben Anweisungen keinen Wert zurück, Ausdrücke hingegen schon. Diese Unterscheidung bedeutet, dass if else-Bedingungen in Rust immer einen Wert zurückgeben. Der Wert kann vom Typ empty() oder ein tatsächlicher Wert sein. Was auch immer die letzte Zeile der geschweiften Klammern ist, sie wird zum Rückgabewert des if else-Ausdrucks. Es ist wichtig zu beachten, dass if- und else-Zweige denselben Rückgabetyp haben sollten.
fn main() { let result = if 1 == 2 { "Warte was?" } anders { „Rost macht Sinn“ }; println!("Weißt du was? {}.", result); }
Wenn der zuzuweisende Wert vom if else-Ausdruck zurückgegeben wird, müssen wir ein Semikolon als Endmarkierung verwenden. Wenn es sich beispielsweise um einen Ausdruck handelt, ist let eine Anweisung, die am Ende ein Semikolon erwartet.
1.3.7 Übereinstimmungsausdruck
Die Match-Ausdrücke von Rust sind sehr einfach und leicht zu verwenden. Sie ähnelt im Grunde einer vereinfachten Version der switch-Anweisung in der C-Sprache und ermöglicht es Benutzern, Entscheidungen auf der Grundlage des Werts der Variablen und der Verfügbarkeit erweiterter Filterfunktionen zu treffen.
fn req_status() -> u32 { 200 } fn main() { let status = req_status(); Spielstatus { 200 => println!("Erfolg"), 404 => println!("Nicht gefunden"), andere => { println!("Anfrage fehlgeschlagen mit Code: {}", other); } } }
Jede Übereinstimmung muss denselben Typ zurückgeben. Darüber hinaus müssen wir einen exakten Abgleich aller möglichen Übereinstimmungswerte durchführen. Rust ermöglicht es uns, die verbleibenden Möglichkeiten zu ignorieren, indem wir Catch All-Variablen (hier Other) oder _ (Unterstrich) verwenden.
1.3.8 Schleife
Etwas wiederholt in Rust zu tun, kann mit drei Konstrukten erreicht werden, nämlich Schleife, while und for. In all diesen Konstrukten sind normalerweise die Schlüsselwörter continue und break enthalten, sodass Sie die Schleife überspringen bzw. ausbrechen können.
fn main() { sei mut x = 1024; Schleife { wenn x < 0 { brechen; } println!("{} noch weitere Läufe", x); x -= 1; } }
Eine zusätzliche Funktion beim Ausführen von Schleifen in Rust ist die Möglichkeit, Schleifencodeblöcke mit Namen zu kennzeichnen. Dies kann in Situationen verwendet werden, in denen Sie zwei oder mehr verschachtelte Schleifen haben und eine davon unterbrechen möchten, nicht nur für Schleifen, die direkt Break-Anweisungen enthalten.
fn silly_sub(a: i32, b: i32) -> i32 { let mut result = 0; 'inkrementieren: Schleife { wenn Ergebnis == a { sei mut dec = b; 'dekrementieren: Schleife { ifdec==0{ break 'inkrement; } anders { Ergebnis -= 1; dez -= 1; } } } anders { Ergebnis = 1; } } Ergebnis } fn main() { sei a = 10; sei b = 4; let result = silly_sub(a, b); println!("{} minus {} ist {}", a, b, result); }
Rust hat auch das Schlüsselwort for, das der in anderen Sprachen verwendeten for-Schleife ähnelt, deren Implementierung jedoch völlig anders ist. Rusts for-Schleife ist im Grunde syntaktischer Zucker für ein leistungsfähigeres Iterationskonstrukt (Iterator). Einfach ausgedrückt funktionieren For-Schleifen in Rust nur mit Typen, die in Iteratoren konvertiert werden können. Ein solcher Typ ist der Range-Typ. Der Typ „Range“ kann sich auf eine Reihe von Zahlen beziehen.
fn main() { print!("Normaler Bereich: "); für i in 0..10 { drucken!("{},", i); } println!(); print!("Inklusive Bereich: "); für i in 0..=10 { drucken!("(),", i); } }
1.3.9 Benutzerdefinierte Datentypen
Benutzerdefinierte Typen sind von Benutzern definierte Typen. Benutzerdefinierte Typen können aus mehreren Typen bestehen. Sie können Wrapper für primitive Typen oder eine Kombination mehrerer benutzerdefinierter Typen sein. Es gibt sie in drei Formen: Struktur, Aufzählung und Union, auch bekannt als Struktur, Aufzählung und Union. Sie ermöglichen Ihnen eine einfachere Darstellung Ihrer Daten. Die Benennungsregeln für benutzerdefinierte Typen folgen CamelCase.
Struktur
In Rust gibt es drei Formen der Strukturdeklaration. Die einfachste davon ist die Unit-Struktur, die mit dem Schlüsselwort struct deklariert wird, gefolgt von ihrem Namen und endet mit einem Semikolon.
struct Dummy; fn main() { let value = Dummy; }
Die zweite Strukturform ist die Tupelstruktur, die über zugehörige Daten verfügt. Jedes dieser Felder wird nicht benannt, sondern anhand seiner Position in der Definition referenziert.
struct Color(u8, u8, u8); fn main() { let white = Color(255, 255, 255); sei rot = weiß.0; sei grün = weiß.1; sei blau = weiß.2; println!("Roter Wert: {}", rot); let orange = Color(255, 165, 0); sei Color(r, g, b) = orange; println!("R: {}, G: {}, B: {} (orange)", r, g, b); sei Color(r, _, b) = orange; }
Tupelstrukturen sind ideal für die Modellierung von Daten mit weniger als 5 Attributen. Jede andere Wahl beeinträchtigt die Lesbarkeit und Argumentation des Codes. Erstellen Sie für Datentypen mit mehr als drei Feldern Strukturen in einer C-ähnlichen Sprache. Dies ist die dritte Form und die am häufigsten verwendete Form.
struct Player { Name: Zeichenfolge, iq: u8, Freunde: u8, Ergebnis: U16 } fn Bump_player_score(mut Spieler: Spieler, Punktestand: u16) { player.score = Punktestand; println!("Aktualisierte Spielerstatistiken:"); } fn main() { let name = "Alice".to_string(); let player = Player { name, iq: 171, Freunde: 134, Punktzahl: 1129 }; Bump_player_score(player, 120); }
aufzählen
Aufzählungen sind eine gute Möglichkeit, dies zu tun, wenn Sie verschiedene Arten von Dingen modellieren müssen. Es wird mit dem Schlüsselwort enum erstellt, gefolgt vom Namen der Aufzählung und einem Paar geschweifter Klammern. Innerhalb der geschweiften Klammern können wir alle möglichen Typen, also Varianten, schreiben. Diese Varianten können mit oder ohne Daten definiert werden, und die enthaltenen Daten können ein beliebiger Ferntyp, eine beliebige Struktur, eine Tupelstruktur oder sogar ein Aufzählungstyp sein.
Enum-Richtung { N, E, S, W } Enum PlayerAction { Bewegen { Richtung: Richtung, Geschwindigkeit: u8 }, Warten, Angriff (Richtung) } fn main() { letsimulated_player_action = PlayerAction::Move { Richtung: Richtung::N, Geschwindigkeit: 2, }; matchsimulated_player_action { PlayerAction::Wait => println!("Spieler möchte warten"), PlayerAction::Move { Richtung, Geschwindigkeit } => { println!("Der Spieler möchte sich mit der Geschwindigkeit {} in Richtung {:?} bewegen", Richtung, Geschwindigkeit) } PlayerAction::Attack(direction) => { println!("Spieler möchte Richtung {:?} annehmen", Richtung) } }; }
1.3.10 Funktionen und Methoden für Typen
Impl-Block auf Struktur
Wir können einer definierten Struktur mithilfe von zwei Mechanismen Verhalten hinzufügen: konstruktorähnliche Funktionen sowie Getter- und Setter-Methoden.
struct Player { Name: Zeichenfolge, iq: u8, Freunde: u8 } impl Spieler { fn with_name(name: &str) -> Spieler { Spieler { Name: name.to_string(), iq: 100, Freunde: 100 } } fn get_friends(&self) -> u8 { Selbst.Freunde } fn set friends(&mut self, count: u8) { self.friends = count; } } fn main() { let mut player = Player::with_name("Dave"); player.set_friends(23); println!("{}s Freunde zählen: {}", player.name, player.get_friends()); let _ = Player::get_friends(&player); }
Zugehörige Methode: Diese Methode hat nicht den Typ „self“ als ersten Parameter. Es ähnelt statischen Methoden in objektorientierten Programmiersprachen. Diese Methoden sind für den Typ selbst aufrufbar und erfordern keinen Aufruf einer Instanz des Typs. Eine zugehörige Methode wird aufgerufen, indem dem Methodennamen der Strukturname und ein Doppelpunkt vorangestellt werden.
Instanzmethode: eine Funktion, die self als ersten externen Parameter verwendet. Das Selbst ähnelt hier dem Selbst in Python und verweist auf die Instanz, die die Methode implementiert.
Impl-Blöcke und Enumerationen
Aufzählungen werden häufig in Zustandsautomaten verwendet und können bei Verwendung mit Übereinstimmungsausdrücken den Zustandsübergangscode sehr prägnant gestalten. Sie können auch zur Modellierung benutzerdefinierter Fehlertypen verwendet werden.
enum PaymentMode { Lastschrift, Kredit, Paypal } fn pay_by_credit(amt: u64) { println!("Kreditzahlung von {} wird verarbeitet", amt); } fn pay_by_debit(amt: u64) { println!("Lastschriftzahlung von {} wird verarbeitet", amt); } fn paypal_redirect(amt: u64) { println!("Weiterleitung zu PayPal für Betrag: {}", amt); } impliziter Zahlungsmodus { fn pay(&self, Betrag: u64) { match self { PaymentMode::Debit => pay_by_debit(amount), PaymentMode::Credit => pay_by_credit(amount), PaymentMode::Paypal => paypal_redirect(Betrag) } } } fn get_saved_paid_mode() -> PaymentMode { Zahlungsmodus::Lastschrift } fn main() { let payment_mode = get_saved_ payment_mode(); payment_mode.pay(512); }
1.3.11 Modul-, Import- und Use-Anweisungen
Programmiersprachen bieten häufig die Möglichkeit, große Codeblöcke in mehrere Dateien aufzuteilen, um die Komplexität zu bewältigen. Java folgt der Konvention, dass jede .java-Datei eine öffentliche Klasse ist, und C stellt uns Header-Dateien und Include-Anweisungen zur Verfügung. Rust bietet einen Modulmechanismus. Module sind eine Möglichkeit, Code in Rust-Programmen zu benennen und zu organisieren.
Jedes Rust-Programm benötigt ein Root-Modul. Bei ausführbaren Dateien ist es normalerweise die Datei main.rs und bei Bibliotheken normalerweise die Datei lib.rs.
Module können innerhalb anderer Module deklariert oder in Dateien und Verzeichnissen organisiert werden.
Damit der Compiler unser Modul erkennt, müssen wir das Schlüsselwort mod-Deklaration verwenden. In unserem Root-Modul müssen wir das Schlüsselwort use vor dem Modulnamen verwenden, was bedeutet, dass das Element in den Gültigkeitsbereich gebracht wird.
In einem Modul definierte Elemente sind standardmäßig privat und müssen Aufrufern über das Schlüsselwort pub zugänglich gemacht werden.
1.3.12 Sammlung
Array
Arrays haben eine feste Länge und können Elemente desselben Typs speichern. Sie werden durch [T, N] dargestellt, wobei T einen beliebigen Typ und N die Anzahl der Array-Elemente darstellt. Die Größe des Arrays kann nicht durch eine Variable dargestellt werden und muss ein Literalwert von usize sein.
Tupel
Projektliste
Schlüssel/Wert-Paar
Scheibe
1.3.13 Iterator
Unterthema
Unterthema
Unterthema
1.4 Zeichenzähler verbessern
1.5 Zusammenfassung
Kapitel 2 Verwenden von Cargo zum Verwalten von Projekten
2.1 Paketmanager
2.2 Module
2.2.1 Verschachtelte Module
2.2.2 Dateien als Module verwenden
2.2.3 Verwendung von Verzeichnissen als Module
2.3 Fracht und Bibliotheken
2.3.1 Erstellen Sie ein neues Cargo-Projekt
2.3.2 Fracht und Abhängigkeiten
2.3.3 Verwendung von Cargo zum Ausführen von Tests
2.3.4 Verwenden von Cargo zum Ausführen des Beispiels
2.3.5 Cargo-Arbeitsbereich
2.4 Cargo-Tool-Erweiterung
2.4.1 Unterbefehle und Cargo-Installation
2.4.2 Verwenden Sie Clippy, um Code zu formatieren
2.4.3 Einführung in die Manifestdatei Cargo.toml
2.5 Richten Sie eine Rust-Entwicklungsumgebung ein
2.6 Verwenden Sie Cargo, um das imgtool-Programm zu erstellen
2.7 Zusammenfassung
Kapitel 3 Testen, Dokumentation und Benchmarking
3.1 Zweck der Prüfung
3.2 Organisation von Tests
3.3 Unit-Tests
3.3.1 Der erste Unit-Test
3.3.2 Ausführen von Tests
3.3.3 Testcode isolieren
3.3.4 Fehlerprüfung
3..3.5 Tests ignorieren
3.4 Integrationstests
3.4.1 Erster Integrationstest
3.4.2 Gemeinsamen Code teilen
3.5 Dokumentation
3.5.1 Dokumentation schreiben
3.5.2 Dokumente erstellen und anzeigen
3.5.3 Gehostete Dokumente
3.5.4 Dokumenteigenschaften
3.5.5 Dokumentierte Tests
3.6 Benchmark
3.6.1 Integrierte Mikro-Benchmark-Tools
3.6.2 Benchmarking der stabilen Version von Rust
3.7 Softwarepakete schreiben und testen – Logikgattersimulator
3.8 CI-Integrationstests und Travis CI
3.9 Zusammenfassung
Kapitel 4 Typen, Generika und Merkmale
4.1 Typsysteme und ihre Bedeutung
4.2 Generika
4.2.1 Generika erstellen#
4.2.2 Generische Implementierung
4.2.3 Allgemeine Anwendungen
4.3 Verwenden von Funktionen zum Abstrahieren von Verhalten
4.3.1 Eigenschaften
4.3.2 Verschiedene Formen von Features
4.4 Verwendung paketgenerischer Features – Feature-Intervalle
4.4.1 Charakteristische Intervalle für Typen
4.4.2 Charakteristische Intervalle für generische Funktionen und Impl-Codeblöcke
4.4.3 Verwenden Sie die Merkmalskombination „ “, um ein Intervall zu bilden
4.4.4 Feature-Intervall und Impl-Feature-Syntax
4.5 Einführung in die Standardfunktionen der Bibliothek
4.6 Verwenden von Merkmalsobjekten, um echten Polymorphismus zu erreichen
4.6.1 Verteilung
4.6.2 Charakteristische Objekte
4.7 Zusammenfassung
Kapitel 5 Speicherverwaltung und Sicherheit
5.1 Programme und Speicher
5.2 Wie Programme Speicher nutzen
5.3 Speicherverwaltung und -klassifizierung
5.4 Einführung in die Speicherzuweisung
5.4.1 Stapel
5.4.2 Haufen
5.5 Mängel in der Speicherverwaltung
5.6 Speichersicherheit
5.7 Drei Prinzipien der Speichersicherheit
5.7.1 Eigentum
5.7.2 Wiederverwendung von Typen durch Merkmale
5.7.3 Kreditaufnahme
5.7.4 Methodentypen basierend auf Borrowing-Regeln
5.7.5 Lebenszyklus
5.8 Zeigertypen in Rust
5.8.1 Referenzen – sichere Zeiger
5.8.2 Rohzeiger
5.8.3 Intelligente Zeiger
5.8.4 Referenzgezählte intelligente Zeiger
5.8.5 Anwendung der internen Variabilität
5.9 Zusammenfassung
Kapitel 6 Ausnahmebehandlung
6.1 Einführung in die Ausnahmebehandlung
6.2 Behebbare Ausnahmen
6.2.1 Option
6.2.2 Ergebnis
6.3 Option/Ergebnis-Kombination
6.3.1 Gemeinsame Kombinatoren
6.3.2 Combiner-Anwendung
6.3.3 Konvertierung zwischen Options- und Ergebnistypen
6.4 Vorzeitige Rückkehr und Betreiber „?“
6.5 Nicht behebbare Ausnahmen
6.6 Benutzerdefinierte Fehler und Fehlermerkmale
6.7 Zusammenfassung
Kapitel 7 Fortgeschrittene Konzepte
7.1 Einführung in Typensysteme
7.1.1 Codeblöcke und Ausdrücke
7.1.2 let-Anweisung
7.1.3 Schleifen als Ausdrücke
7.1.4 Typklarheit und Symbolunterscheidung in numerischen Typen
7.1.5 Typinferenz
7.1.6 Typ-Aliase
7.2 Zeichenfolge
7.2.1 String, der den Besitz enthält – String
7.2.2 Ausleihzeichenfolge——&str
7.2.3 String-Slicing und Chunking
7.2.4 Verwendung von Strings in Funktionen
7.2.5 String-Verkettung
7.2.6 Anwendungsszenarien von &str und String
7.3 Globale Werte
7.3.1 Konstanten
7.3.2 Statische Werte
7.3.3 Funktion zur Kompilierungszeit – const fn
7.3.4 Dynamische statische Werte über das Makro lazy_static
7.4 Iteratoren
7.5 Erweiterte Typen
7.5.1 Typen mit unbestimmter Länge
7.5.2 Funktionstypen
7.5.3 Geben Sie niemals „!“ und die Funktion „Dispatch“ ein
7.5.4 Union
7.5.5 Kuh
7.6 Erweiterte Funktionen
7.6.1 Größe und Größe
7.6.2 Ausleihen und AsRef
7.6.3 ToBoned
7.6.4 Von und nach
7.6.5 Charakteristische Objekte und Objektsicherheit
7.6.6 Allgemeine Funktionsaufrufsyntax
7.6.7 Feature-Regeln
7.7 Erweiterte Schließungen
7.7.1 Fn-Schließung
7.7.2 FnMut-Abschluss
7.7.3 FnOnce-Abschluss
7.8 Konstanten in Strukturen, Aufzählungen und Merkmalen
7.9 Module, Pfade und Importe
7.9.1 Importieren
7.9.2 Erneut importieren
7.9.3 Datenschutz
7.10 Erweiterte Matching-Muster und Guards
7.10.1 Match Guard
7.10.2 Erweiterter Mietbau
7.11 Gießen
7.12 Typen und Speicher
7.12.1 Speicherausrichtung
7.12.2 std::mem-Modul
7.13 Serialisierung und Deserialisierung mit serde
7.14 Zusammenfassung
Kapitel 8 Parallelität
8.1 Programmausführungsmodell
8.2 Parallelität
8.2.1 Gleichzeitige Methoden
8.2.2 Mängel
8.3 Parallelität in Rust
8.3.1 Thread-Grundlagen
8.3.2 Benutzerdefinierte Threads
8.3.3 Zugriff auf Daten in Threads
8.4 Thread-Parallelitätsmodell
8.4.1 State-Sharing-Modell
8.4.2 Gegenseitiger Ausschluss
8.4.3 Gemeinsame Veränderlichkeit durch Arc und Mutex
8.4.4 Kommunikation per Messaging
8.5 Gewindesicherheit in Rust
8.5.1 Was ist Thread-Sicherheit?
8.5.2 Eigenschaften der Thread-Sicherheit
8.5.3 Senden
8.5.4 Synchronisierung
8.6 Parallelität mithilfe des Akteurmodells implementieren
8.7 Andere Bibliotheken
8.8 Zusammenfassung
Kapitel 9 Makros und Metaprogrammierung
9.1 Was ist Metaprogrammierung?
9.2 Anwendungsszenarien von Rust-Makros
9.3 Makros und ihre Typen in Rust
9.4 Erstellen Sie Makros mit Macro_rules!
9.5 Integrierte Makros in der Standardbibliothek
9.6 Macro_rules! Makro-Tag-Typ
9.7 Wiederholung in Makros
9.8 Erweiterte Anwendung von Makros – DSL für die HashMap-Initialisierung schreiben
9.9 Makro-Anwendungsfälle – Tests schreiben
9.10 Übung
9.11 Prozessmakros
9.12 Abgeleitete Makros
9.13 High-Level-Makros
9.14 Häufig verwendete Prozessmakro-Softwarepakete
9.15 Zusammenfassung
Kapitel 10 Unsicherer Rost und externe Funktionsschnittstellen
10.1 Sicherheit und Unsicherheit
10.1.1 Unsichere Funktionen und Codeblöcke
10.1.2 Unsichere Eigenschaften und Implementierungen
10.2 C-Code in Rust aufrufen
10.3 Aufrufen von Rust-Code über die C-Sprache
10.4 Verwendung externer C/C-Bibliotheken in Rust
10.5 Erstellen nativer Python-Erweiterungen mit PyO3
10.6 Erstellen nativer Erweiterungen für Node.js in Rust
10.7 Zusammenfassung
Kapitel 11 Protokoll
11.1 Protokollierung und ihre Bedeutung
11.2 Anforderungen an ein Logging-Framework
11.3 Protokollierungsframework und seine Funktionen
11.4 Protokollierungsmethode
11.4.1 Unstrukturierte Protokollierung
11.4.2 Strukturierte Protokollierung
11.5 Einloggen in Rust
11.5.1 log – Protokollierung für Rust
11.5.2 env_logger
11.5.3 log4rs
11.5.4 Verwendung von slog zur strukturierten Protokollierung
11.6 Zusammenfassung
Kapitel 12 Rust und Netzwerkprogrammierung
12.1 Einführung in die Netzwerkprogrammierung
12.2 Synchrone Netzwerk-E/A
12.3 Asynchrone Netzwerk-E/A
12.3.1 Asynchrone Abstraktionen in Rust
12.3.2 Aufbau eines asynchronen Redis-Servers
12.4 Zusammenfassung
Kapitel 13 Webanwendungen mit Rust erstellen
13.1 Webanwendungen in Rust
13.2 Verwendung von Hyper für die HTTP-Kommunikation
13.2.1 Die hyperserverseitige API erstellt einen kurzen URL-Dienst
13.2.2 Hyper als Client – Aufbau eines URL-Kurzclients
13.2.3 Web-Framework
13.3 Actix-web-Grundkenntnisse
13.4 Erstellen einer Lesezeichen-API mit actix-web
13.5 Zusammenfassung
Kapitel 14 Rust und WebAssembly
14.1 Die Bedeutung der Datenhaltbarkeit
14.2 SQLite
14.3 PostgreSQL
14.4 R2D2-Verbindungspool
14.5 Postgres und Diesel ORM
14.6 Zusammenfassung
Kapitel 15 Rust und WebAssembly
15.1 Was ist WebAssmbly?
15.2 Designziele von WebAssembly
15.3 Erste Schritte mit WebAssembly
15.3.1 Online testen
15.3.2 Methoden zum Generieren von WebAssembly
15.4 Rust und WebAssembly
15.4.1 wasm-bindgen
15.4.2 Andere WebAssembly-Projekte
15.5 Zusammenfassung
Kapitel 16 Rust- und Desktop-Anwendungen
16.1 Einführung in die GUI-Entwicklung
16.2 GTK-Framework
16.3 Erstellen Sie eine News-Desktop-Anwendung über gtk-rs
16.4 Übungen
16.5 Andere neue UI-Frameworks
16.6 Zusammenfassung
Kapitel 17 Debuggen
17.1 Einführung in das Debuggen
17.1.1 Debugger-Grundlagen
17.1.2 Voraussetzungen zur Inbetriebnahme
17.1.3 GDB konfigurieren
17.1.4 Ein Beispielprogramm – Buggie
17.1.5 GDB-Grundlagen
17.1.6 GDB in Visual Studio Code integrieren
17.2 Einführung in den rr-Debugger
17.3 Zusammenfassung