Strona główna / Artykuły

Nauka języka Rust poprzez dziesięć projektów, od narzędzi CLI po usługi inferencji.

Stopniowana lista dziesięciu projektów w języku Rust, od narzędzia CLI do skanowania plików po klon Redis oraz usługę shell i inferencji, wraz z tym, czego każdy z nich uczy na temat pamięci, równoległości i radzenia sobie z błędami.

Wydawca: REACTAPP.TOP11 min czytania2566 słów

Źródła: 10 Rust Projects That Will Actually Make You Better at Programming in 2026

Wielu programistów, którzy zaczynają pracę z językiem Rust, spędza tygodnie na studiowaniu składni i tutoriali, a potem zatrzymuje się przy pierwszej próbie stworzenia czegoś rzeczywistego. Znajomość słów kluczowych to nie to samo, co zrozumienie, dlaczego mechanizm sprawdzania pożyczek odrzuca twój projekt, jak zadania asynchroniczne dzielą się stanem lub co powinno się stać, gdy sokiet zostanie zamknięty w trakcie żądania. Niezawodnym sposobem na przezwyciężenie tej luki jest tworzenie projektów, które sprawiają, że te pytania stają się nieuniknione. Ten przewodnik przedstawia dziesięć takich projektów w rosnącej kolejności trudności, wyjaśnia, czego każdy z nich zmusza do nauczenia się, oraz opisuje nawyki (iteracja, testowanie, benchmarking i zdyscyplinowane wykorzystanie sztucznej inteligencji), które przekształcają ukończony projekt w prawdziwą umiejętność.

Dlaczego projekty są lepsze od zapamiętywania składni

Rust znajduje zastosowanie w oprogramowaniu systemowym, infrastrukturze chmurowej, narzędziach dla programistów, produktach związanych z bezpieczeństwem, platformach blockchain oraz w niektórych elementach infrastruktury sztucznej inteligencji. Ta szeroka gama zastosowań sprawia, że jego nauka jest atrakcyjna, ale jednocześnie ułatwia też tylko powierzchowne poznanie. Możesz zapamiętać wszystkie te kluczowe pojęcia:

let
mut
fn
struct
enum
trait
impl

a mimo to utknąć, gdy prawdziwy program wymaga wspólnego, zmiennej stanu pomiędzy wątkami. Najbardziej przydatne projekty edukacyjne nie muszą być dużymi aplikacjami – to te, które pomagają zrozumieć, dlaczego język został zaprojektowany w taki sposób, ponieważ stawiają użytkownika w sytuacjach, w których proste podejście nie kompiluje się lub nie funkcjonuje przy rzeczywistych danych wejściowych.

1. Narzędzie wiersza poleceń rozwiązujące rzeczywisty problem

Zacznij od małego, wybierając coś, czego faktycznie będziesz używał. Dobrymi kandydatami są analizator logów, narzędzie do wyszukiwania plików, narzędzie do pięknego wyświetlania danych w formacie JSON, procesor plików CSV, generator haseł, skaner katalogów lub konwerter do formatu Markdown.

Naprzимер, skaner logów można uruchomić w ten sposób:

$ logscan app.log --level error

i wyświetlić streszczenie wraz z odpowiadającymi mu liniami (pierwsza linia wyniku została tu wyświetlona razem ze streszczeniem):

Found 42 errors12:31:04 Database connection failed
12:31:09 Request timeout
12:31:15 Authentication service unavailable

Nawet tak małe narzędzie obejmuje zaskakująco dużo aspektów języka:

  • parowanie argumentów z linii poleceń
  • czytanie plików i obsługa błędów wejścia/wyjścia
  • praca z typem String w porównaniu z &str
  • modelowanie danych za pomocą struktur i typów wybieralnych
  • przenoszenie błędów za pomocą typu Result i operatora ?
  • organizacja kodu w moduły
  • pisanie testów jednostkowych

Równie ważne jest to, że narzędzie to jest na tyle małe, by można je ukończyć. Wysyłanie kompletnego produktu to odrębna umiejętność, a ukończone małe narzędzie uczy więcej niż porzucone, ambitne przedsięwzięcie.

2. Minimalny serwer HTTP bez frameworka

Zanim sięgniesz po framework internetowy, napisz prosty serwer HTTP oparty na TCP. Ścieżka żądania, którą ostatecznie zaimplementujesz, wygląda mniej więcej tak:

Client
  ↓
TCP connection
  ↓
HTTP parser
  ↓
Router
  ↓
Handler
  ↓
Response

W trakcie tego procesu poznasz TCP i sockets, strukturę wiadomości HTTP, parsowanie żądań, tworzenie odpowiedzi, zarządzanie buforami, kwestię własności danych przekazywanych pomiędzy poszczególnymi etapami oraz obsługę kilku połączeń jednocześnie. Serwer nie musi być gotowy do użycia w produkcji; kluczowe jest zrozumienie mechanizmów. Gdy już sam to zrobisz ręcznie, frameworki takie jak Axum czy Actix Web przestaną wydawać się czymś magicznym, ponieważ dokładnie wiesz, jakie zadania od ciebie przejmują.

3. REST API wspierany przez rzeczywistą bazę danych

Następnie przybliżmy się do prawdziwego backendu. Dobrym obszarem do rozpoczęcia jest API do zarządzania zadaniami, które obejmuje standardowe ścieżki do zasobów:

POST   /tasks
GET    /tasks
GET    /tasks/:id
PUT    /tasks/:id
DELETE /tasks/:id

Następnie dodaj warstwy PostgreSQL, autoryzację, walidację, ustrukturyzowane odpowiedzi na błędy, logowanie, zarządzanie konfiguracją oraz testy integracyjne. To właśnie tutaj poszczególne cechy języka zaczynają łączyć się w architekturę, a pojawiają się ważniejsze pytania: która warstwa powinna obsługiwać daną część logiki, co API powinno robić, gdy baza danych jest niedostępna, jaki stan i treść powinien otrzymać klient, w jaki sposób błędy powinny być przekazywane z warstwy przechowywania do odpowiedzi HTTP oraz jak konfiguracja powinna się różnić w poszczególnych środowiskach. Te kwestie projektowe są o wiele ważniejsze niż jakakolwiek pojedyncza zasada składni.

4. Współbieżny crawler internetowy

Teraz zwiększmy poziom trudności. Bot, który pobiera wiele stron jednocześnie, rozprzestrzenia się od punktu startowego w ten sposób:

┌── URL 1
             │
Start ───────┼── URL 2
             │
             ├── URL 3
             │
             └── URL 4

Dodaj wyraźny limit dla równoległości:

Maximum concurrent requests: 10

To jedno ograniczenie zmusza cię do zrozumienia koncepcji współbieżności, zamiast tworzyć zadania i mieć nadzieję na najlepszy wynik. Będziesz pracować z funkcjami i zadaniami asynchronicznymi, kanałami, wspólnym stanem oraz wymaganą synchronizacją, timeoutami, próbami ponownych działań i ograniczeniami szybkości. Napotkasz również problemy, które nigdy nie występują w programach sekwencyjnych, takie jak odwiedzenie tej samej adresu URL dwukrotnie z dwóch różnych zadań lub powolny serwer, który spowalnia pozostałe. Właśnie te problemy sprawiają, że projekt jest wart stworzenia.

5. Magazyn typu klucz-wartość

Niewielka baza danych to jeden z najbardziej satysfakcjonujących projektów edukacyjnych. Zacznij od trzech poleceń:

SET name Rothy
GET name
DELETE name

Następnie rozwijaj to rozwiązanie poprzez zapisywanie danych na dysku, indeksowanie, serializację, wygaszanie kluczy, transakcje oraz bezpieczny dostęp równoległy. Nie próbuj konkurować z Redisem – chodzi o zrozumienie, jak działają silniki przechowywania danych. Projekt ćwiczy struktury danych, operacje wejścia/wyjścia z plikami, układ pamięci, formaty serializacji, równoległość, gwarancje trwałości oraz wydajność. To również tutaj model własności w Rust zaczyna być przydatny, a nie przeszkodą, ponieważ zarządzasz teraz długowiecznym stanem, do którego chcą mieć dostęp różne części programu.

6. Miniatury serwera Redis

Jeśli interesuje cię przechowywanie danych w formacie klucz-wartość, przekształć to w mały serwer sieciowy, który używa protokołu podobnego do Redis:

SET user:1 Rothy
GET user:1
DEL user:1

i obsługuj wygaszanie kluczy na podstawie czasu:

EXPIRE user:1 60

Z upływem czasu można dodać połączenia TCP od wielu klientów, analizę poleceń, obsługę zapytań równolegle, przechowywanie w pamięci, mechanizmy trwałości danych, określanie terminu ważności oraz testy wydajności. Projekt łączy w sobie tematy związane z sieciami, strukturami danych, równoległością i projektowaniem systemów, zmuszając do rozważania różnych kompromisów. Czy serwer powinien optymalizować się pod kątem opóźnienia, przepustowości, zużycia pamięci czy trwałości? Rzadko istnieje jedna prawidłowa odpowiedź, a umiejętność świadomego wyboru oraz jego uzasadnienia to jedna z najbardziej przydatnych lekcji na tej liście.

7. Kolejka zadań z pracownikami

Kolejka zadań to doskonała praktyka dla systemów backendowych. Podstawowy przepływ jest następujący:

Producer
   ↓
Job Queue
   ↓
Workers
   ↓
Results

Zadania reprezentują jednostki pracy, takie jak:

send_email
generate_report
process_image
run_test

Zacznij od robotów, które wielokrotnie pobierają kolejne zadanie i je wykonywają. Następnie dodaj kilka robotów, możliwość ponawiania prób, śledzenie stanu zadań, czas wygaśnięcia, obsługę błędów oraz płynne zamykanie, aż projekt będzie wyglądać w ten sposób:

Producer
    ↓
┌───────────────┐
│   Job Queue   │
└───────────────┘
   ↓    ↓    ↓
Worker Worker Worker

Główna lekcja polega na tym, że oprogramowanie dotyczy nie tylko scenariusza pomyślnego działania. Kolejka zadań pozwala określić, co się stanie, gdy zadanie zawiedzie w trakcie wykonywania, gdy robot się zatrzyma lub gdy proces ma zostać zakończony, podczas gdy praca jest jeszcze w trakcie. Projektowanie z myślą o takich sytuacjach odróżnia demonstrację od prawdziwego systemu.

8. Agregator logów

Dla czegoś, co bardziej przypomina praktykę w środowisku produkcyjnym, stwórz małą usługę do zbierania logów. Kilka aplikacji wysyła swoje logi do jednego agregatora, który je przechowuje:

Application A ──┐
Application B ──┼──> Log Collector ──> Storage
Application C ──┘

Agregator może przyjmować logi przez HTTP lub surowy protokół TCP oraz udostępniać API do wyszukiwania:

GET /logs?level=error
GET /logs?service=payment
GET /logs?from=...

Praca obejmuje sieciowanie, serializację, jednoczesne pobieranie danych, filtrowanie, obsługę zapisu daty i czasu, układ przechowywania, wydajność oraz możliwości monitorowania. To także doskonałe miejsce, by dowiedzieć się, jak serwis zachowuje się pod obciążeniem: co się dzieje, gdy tempo pobierania danych przewyższa możliwości przechowywania, ile pamięci jest potrzebne na buforowanie oraz jak zmienia się szybkość wykonywania zapytań wraz ze wzrostem ilości danych.

9. Mała skrypcja w stylu Unix

Ten projekt jest trudny, a właśnie to czyni go przydatnym. Zacznij od wykonywania prostych poleceń:

$ echo hello
hello

oraz obsługi funkcji wbudowanych razem z programami zewnętrznymi (wyświetlany tekst drugiego polecenia został tutaj połączony z wynikiem pierwszego):

$ pwd
/home/user$ ls
file1.txt
file2.txt

Następnie dodaj wykonywanie poleceń, zmienne środowiskowe, rury przepływu danych, przekierowanie wyjścia, procesy w tle oraz obsługę sygnałów, rozwijając się aż do budowy bardziej złożonych łańcuchów poleceń.

cat access.log | grep ERROR | sort

W tym momencie programujesz w bliskiej odległości od systemu operacyjnego. Dowiadujesz się, jak tworzone i zarządzane są procesy, jak połączone są stdin, stdout i stderr, jak dziedziczone są zmienne środowiskowe, jak rury łączą procesy oraz jakie API systemu operacyjnego leżą u ich podstaw. Niewiele projektów tak skutecznie wyjaśnia to, co naprawdę dzieje się, gdy naciskasz klawisz Enter w terminalu.

10. Mała usługa inferencji AI

Ostatni projekt odzwierciedla obszar, w którym realizowane są liczne nowe inicjatywy infrastrukturalne. Celem nie jest trenowanie modelu, lecz stworzenie usługi opartej na takim modelu:

Client
  ↓
Rust API
  ↓
Request Queue
  ↓
Inference Worker
  ↓
Model
  ↓
Response

Przydatna usługa przyjmuje żądania inferencji, weryfikuje dane wejściowe, umieszcza zadania w kolejce, przetwarza żądania równolegle, zwraca wyniki, rejestruje opóźnienia, egzekwuje limity czasowe i udostępnia metryki. Najciekawsze aspekty inżynieryjne znajdują się w infrastrukturze, a nie w modelu. Można eksperymentować z ograniczeniami równoległości, grupowaniem żądań, cache’owaniem, kontrolą dostępu, zużyciem pamięci, budżetami opóźnień, próbami ponownymi oraz możliwościami obserwacji. To właśnie tutaj kontrola Rust nad pamięcią i równoległością staje się bezpośrednio istotna dla systemów stanowiących podstawę aplikacji AI.

Zajmij się dogłębnie jednym projektem zamiast pobieżnie dziesięcioma

Nie musisz budować tutaj każdego projektu, a próba tego zazwyczaj jest błędem. Wybierz jeden, dokończ go, a następnie kontynuuj jego udoskonalanie. Pierwszym kamieniem milowym może być:

Version 1
Basic functionality

Następują po tym kolejne wersje, z których każda dodaje jedną nową funkcjonalność (strzałki i etykiety wersji są pokazane razem w tym wykazie):

        ↓Version 2
Better error handling        ↓Version 3
Tests        ↓Version 4
Concurrency        ↓Version 5
Persistence        ↓Version 6
Benchmarking        ↓Version 7
Production-style monitoring

Większość nauki odbywa się w tym cyklu ulepszeń. Każda nowa wersja zmusza do ponownego przemyślenia wcześniejszych decyzji, a refaktoryzacja własnego kodu zgodnie z nowymi wymaganiami uczy o wiele więcej niż rozpoczynanie kolejnego projektu od zera.

Pytania, których uczy się zadawać dzięki tym projektom

Nauka języka Rust nie jest prawdziwym celem; celem jest nauka myślenia o oprogramowaniu. Powyższe projekty stale stawiają przed nami te same rodzaje pytań:

  • Pamięć: kto jest właścicielem tych danych i jak długo istnieją?
  • Konkurencja: co się stanie, jeśli dwie zadania będą pracować z tymi danymi w tym samym momencie?
  • Błędy: co powinno się stać, gdy ta operacja zawiedzie?
  • Sieciowanie: co się stanie, jeśli klient odłączy się w trakcie pracy?
  • Wydajność: gdzie znajduje się rzeczywisty wąskie gardło?
  • Bезpieczeństwo: które dane wprowadzane przez użytkownika są pod jego kontrolą?
  • Niezawodność: co się dzieje, gdy jakaś zależność przestaje działać?
  • To pytania mają zastosowanie we wszystkich językach. Rust po prostu sprawia, że musisz stawić czoła wielu z nich wcześniej, często już podczas kompilacji, a nie w środowisku produkcyjnym.

    Zalecany plan rozwoju

    Jeśli zaczynasz od zera, wspinaj się po drabinie krok po kroku, zamiast od razu przechodzić do najtrudniejszego poziomu:

    • Początkujący: narzędzie CLI, do nauki podstaw języka i obsługi błędów.
    • Początkujący do poziomu średniego: serwer HTTP, dla tematów związanych z sieciowaniem i koncepcjami niższego poziomu.
    • Poziom średni: API REST, dla prawdziwej architektury backendu.
    • Poziom średni: narzędzie do przeszukiwania w tle, dla kodu asynchronicznego i konkurencyjnego.
    • Poziom średni do zaawansowanego: magazyn typu klucz-wartość, do przechowywania danych i zarządzania stanem.
    • Rozwijane: klon Redis, łączący sieciowanie, równoczesność i przechowywanie danych.
    • Rozwijane: kolejka zadań, służąca do myślenia w kategoriach systemów rozproszonych.
    • Rozwijane: agregator logów, przydatny do zapewnienia widoczności i rozwiązywania problemów w środowisku produkcyjnym.
    • Rozwijane: shell, dotyczący koncepcji systemów operacyjnych.
    • Zorientowane na przyszłość: usługa inferencji, łącząca Rust z nowoczesną infrastrukturą AI.

    Testowanie od pierwszego dnia

    Nie odkładaj testowania na koniec. Dla każdego projektu sprawdź normalne zachowanie, nieprawidłowe dane wejściowe, puste dane wejściowe, warunki brzegowe, operacje równoczesne, ścieżki awarii, czas wygaśnięcia i możliwości odzyskania. Jeśli punkt końcowy wymaga identyfikatora użytkownika, jeden taki test nie wystarczy:

    GET /users/123
    

    Przetestuj również liczby zerowe, ujemne, wartości nieliczbowe, bardzo duże identyfikatory oraz brakujące segmenty:

    GET /users/0
    GET /users/-1
    GET /users/abc
    GET /users/999999999
    GET /users/
    

    Tutaj programowanie i testowanie łączą się w jedną dziedzinę. Program, który działa tylko wtedy, gdy wszystko idzie gładko, nie jest ukończony. Wbudowany w Rust narzędzie cargo test ułatwia przechowywanie takich przypadków obok kodu.

    Benchmark zamiast domysłów

    Rust słynie ze swojej szybkości, dlatego lepiej ją zmierzyć niż tylko o niej przypuszczać. Test obciążeniowy Twojego serwera może dać raport w podobnym kształcie; liczby są jedynie ilustracyjne, a Twoje wyniki będą zależeć wyłącznie od sprzętu i obciążenia:

    Requests:       100,000
    Average:        4.2 ms
    P95:            7.1 ms
    P99:            11.4 ms
    Throughput:     23,800 req/s
    

    Zapisz wartość wyjściową, zmień jedną rzecz i zmierz ponownie. Zwracaj uwagę na opóźnienia typu P95 i P99, a nie tylko na średnią, ponieważ to właśnie tam zwykle pojawiają się problemy z konkurencją i alokacją pamięci. Mierzenie przed i po zmianach to nawyk, który sprawia, że optymalizacje opierają się na faktach, a nie na domysłach.

    Wykorzystuj asystentów AI bez pomijania nauki

    Narzędzia do programowania oparte na AI mogą teraz generować dla ciebie wiele kodu w języku Rust: struktury, obsługę API, testy, zapytania do bazy danych, typy błędów oraz dokumentację. Jest to rzeczywiście przydatne, ale jeśli celem projektu jest rozwój umiejętności jako programisty, przekazywanie mu całkowitego procesu myślenia podważa ten cel. Lepszym podejściem jest samodzielne zaprojektowanie rozwiązania, jego implementacja, a dopiero potem poproszenie asystenta o sprawdzenie – na przykład o weryfikację problemów z własnością, błędów konkurencyjnych, luk w obsłudze błędów oraz niepotrzebnych alokacji pamięci. Tego typu przegląd coś cię uczy; prośba o całe aplikacje tego nie robi. Chodzi nie o unikanie AI, lecz o jego wykorzystywanie bez rezygnacji z nauki.

    Co obejmuje pełny zestaw

    Dokonanie prawidłowo nawet trzech lub czterech z tych projektów zapozna cię z szerokim zakresem inżynierii oprogramowania:

    Rust
     │
     ├── Ownership
     ├── Borrowing
     ├── Error handling
     ├── Traits
     ├── Generics
     │
     ├── Networking
     ├── Concurrency
     ├── Async programming
     │
     ├── Databases
     ├── APIs
     ├── Operating systems
     │
     ├── Testing
     ├── Benchmarking
     ├── Observability
     │
     └── System design
    

    Taka szerokość horyzontów jest o wiele cenniejsza niż kolejny ukończony tutorial.

    Główne wnioski

    • Wybieraj projekty, które zmuszają cię do zmierzenia się z kwestiami odpowiedzialności, równoczesności i awarii, a nie tylko z składnią.
    • Zacznij od czegoś małego, co możesz ukończyć, a następnie przechodź do tematów związanych z sieciami, przechowywaniem danych i pracą na poziomie systemu operacyjnego.
    • Dopracowuj jeden projekt poprzez kilka wersji, zamiast rozpoczynać wiele projektów jednocześnie.
    • Od samego początku testuj przypadki krawędziowe i ścieżki awarii, a także sprawdzaj efektywność każdego zapewnianego ulepszenia.
    • Pozwól sztucznej inteligencji przejrzeć twój projekt i kod, ale samodzielnie zajmij się projektem.
    • Najlepszym następnym projektem jest ten, który pomoże ci zrozumieć coś, czego obecnie nie wiesz: zacznij od małych kroków, sprawdź to, przetestuj, przeanalizuj, napraw i potem utrudnij zadanie.

    Pozycje pokrewne

  • Pięć projektów w Rust do nauki, z etapami i ograniczeniami AI — Jak wybrać projekt w Rust, który zmusi cię do nauki koncepcji własności, obsługi asynchronicznej i równoległości, poprzez pięć określonych pomysłów, stopniowych etapów oraz zasad korzystania z AI podczas nauki.