Dokumentasi ditelusuri 22 Oktober 2026
Belajar Rust dari Nol: Panduan Lengkap, 20 Contoh Kode, CLI, dan API Web

Ilustrasi ImageGen untuk panduan belajar Rust. Gambar bukan screenshot dan bukan bukti hasil benchmark. Salin kode dari teks atau folder kode, bukan dari gambar.
Anda ingin mempelajari Rust, tetapi setiap tutorial terasa cepat masuk ke istilah ownership, borrowing, dan lifetime? Mulailah dari pekerjaan yang bisa dilihat hasilnya: menampilkan teks, mengolah data kecil, membaca berkas, lalu membuat layanan HTTP. Sesudah itu, gunakan konsep Rust untuk menjelaskan mengapa program boleh atau tidak boleh melakukan suatu tindakan.
Panduan ini menyediakan 20 contoh dasar yang berdiri sendiri, tiga contoh kesalahan kompilasi untuk dipelajari, proyek pencarian teks di terminal, serta proyek API katalog dengan Axum. Semua contoh memakai data buatan. Anda tidak perlu memindahkan website aktif, menyiapkan database, atau membeli server untuk mengikuti bagian inti.
Contoh inti memakai Rust Edition 2024. Edition adalah pengaturan kompatibilitas bahasa dalam manifest, bukan nomor rilis compiler. Cargo menuliskannya pada bagian [package] di Cargo.toml. Ikuti stable toolchain resmi ketika memulai, lalu catat versi yang dipakai untuk proyek Anda. Cargo Manifest (diakses 2026/10), edition.
Tujuan artikel adalah membantu Anda memahami alur program, membaca pesan compiler, dan menyelesaikan proyek yang dapat dijalankan ulang. Jadwal belajar dan pilihan proyek merupakan saran editorial. Penjelasan fitur bersandar pada dokumentasi resmi yang ditelusuri melalui Parallel Search dan TinyFish pada 22 Oktober 2026. Rincian pemeriksaan aktual paket tersedia di hasil-uji.txt.
Daftar isi panduan
1. Apa itu Rust dan mengapa layak dipelajari?
Rust mengelola memori melalui aturan ownership yang diperiksa compiler. Pendekatan ini memungkinkan jaminan keamanan memori tanpa garbage collector. Program yang melanggar aturan ownership akan ditolak sebelum dapat dijalankan. Namun, ada operasi tertentu yang memerlukan unsafe dan tanggung jawab tambahan dari penulis kode. Rust Ownership (diakses 2026/10), pengantar; Rust Unsafe (diakses 2026/10), Unsafe Rust.
Bagi pembelajar, nilai utamanya adalah kesempatan memahami siapa yang memiliki data, kapan data dipinjam, dan bagaimana kesalahan dikembalikan secara eksplisit. Rekomendasi kami adalah mempelajarinya lewat fungsi kecil. Jangan menilai kemajuan hanya dari berapa banyak baris yang berhasil dibuat; cobalah menjelaskan alasan sebuah fungsi menerima String, &str, atau &mut String.
Rust juga mempunyai ekosistem untuk aplikasi jaringan. Axum menyediakan routing dan penanganan permintaan HTTP, sedangkan Tokio menyediakan runtime untuk kode asinkron. Ini menjadi dasar proyek web di bagian akhir artikel. Axum (diakses 2026/10), Compatibility dan Example; Tokio Tutorial (diakses 2026/10), pengantar.
Jangan memakai artikel ini sebagai janji bahwa semua aplikasi Rust selalu lebih cepat, lebih murah, atau bebas celah. Panduan ini tidak membandingkan performa Rust dengan PHP, Go, atau Python. Jika tujuan Anda adalah memilih bahasa untuk tim, buat prototipe kecil dan nilai kemudahan perawatan, kemampuan tim, serta hasil pengukuran pada kebutuhan sendiri.
Untuk siapa panduan ini?
Panduan ini ditujukan untuk pembaca yang sudah dapat menggunakan editor teks dan terminal, termasuk yang sebelumnya belajar PHP, JavaScript, atau Python. Jika belum pernah menulis program, tetap ikuti bagian dasar, tetapi berikan waktu tambahan untuk fungsi, tipe data, dan alur kontrol sebelum melanjutkan proyek API.
Sebagai saran belajar, selesaikan jalur dasar terlebih dahulu, kemudian CLI, baru API. Apabila tujuan Anda hanya membuat alat bantu lokal, proyek CLI sudah menjadi hasil yang utuh. Proyek web disediakan sebagai tahap berikutnya, bukan syarat untuk menyatakan bahwa latihan sebelumnya bermanfaat.
2. Istilah Rust yang perlu dikenali
| Istilah | Arti praktis |
|---|---|
rustc |
Compiler Rust yang mengubah kode menjadi program |
| Cargo | Alat build dan pengelola paket Rust |
| Crate | Unit kompilasi Rust; dapat berupa library atau binary |
| Package | Paket Cargo yang dijelaskan oleh manifest |
| Ownership | Aturan kepemilikan nilai yang membantu pengelolaan memori |
| Borrowing | Mengakses nilai melalui reference tanpa mengambil ownership |
String |
Teks UTF-8 yang dimiliki dan dapat berkembang |
&str |
Reference ke potongan teks UTF-8 |
Option<T> |
Nilai yang mungkin ada atau tidak ada |
Result<T, E> |
Hasil operasi yang dapat sukses atau gagal |
| Trait | Kontrak perilaku yang dapat diterapkan suatu tipe |
| Lifetime | Hubungan masa berlaku reference |
| Async runtime | Lingkungan untuk menjalankan tugas asinkron |
Istilah Cargo, crate, dan package mengikuti Cargo Book (diakses 2026/10), Hello Cargo. Istilah bahasa dijelaskan lebih lanjut pada Rust Borrowing, Rust Strings, Rust Enum, Rust Result, Rust Traits, dan Rust Lifetimes, seluruhnya diakses 2026/10.
Tidak perlu menghafal tabel ini sekaligus. Saat suatu istilah muncul pada pesan error, kembali ke contoh yang relevan dan cari hubungan dengan data yang sedang Anda olah. Cara ini membuat istilah lebih mudah dihubungkan dengan perilaku program.
3. Instal Rust di Windows, Linux, atau macOS

Ilustrasi ImageGen: persiapan alat pengembangan. Tampilan terminal bersifat ilustratif.
Rustup adalah alat instalasi dan pengelolaan versi Rust yang direkomendasikan halaman resmi. Instalasi Rustup juga menyediakan Cargo. Pada Windows, halaman resmi menyediakan installer dan menjelaskan bahwa Visual Studio C++ Build Tools dapat diperlukan. Rust Getting Started (diakses 2026/10), Installing Rust.
Windows dengan PowerShell
Buka halaman resmi Rust di atas, unduh installer sesuai arsitektur komputer, dan ikuti instruksinya. Jika installer meminta alat linker C++, pasang komponen yang diminta sebelum mengulang proses. Setelah selesai, tutup dan buka kembali PowerShell agar perubahan PATH terbaca.
Periksa instalasi:
rustc --version
cargo --version
rustup show
Hasil yang dicari adalah versi compiler, versi Cargo, dan toolchain aktif. Tidak perlu mencocokkan nomor versi Anda persis dengan mesin yang digunakan untuk menyiapkan paket ini. Simpan nomor versi itu dalam catatan proyek jika Anda akan membagikan hasil latihan.
Linux dan macOS
Halaman resmi menampilkan perintah instalasi Rustup untuk sistem Unix. Anda dapat membuka dan meninjau instruksi tersebut sebelum menjalankannya. Setelah instalasi, buka ulang terminal atau ikuti petunjuk konfigurasi shell yang ditampilkan installer. Rust Getting Started (diakses 2026/10), Installing Rust.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustc --version
cargo --version
Apabila compiler sudah terpasang tetapi linker gagal, baca pesan error secara utuh dan periksa paket alat build sistem operasi. Hindari mengganti pengaturan proyek secara acak hanya agar pesan error berganti. Tanda tahap ini selesai adalah program kecil dapat dibangun, bukan sekadar perintah rustc --version berhasil.
Alat editor, format, dan pemeriksaan tambahan
Anda boleh memakai editor yang sudah nyaman. Tambahkan dukungan Rust bila tersedia. Paket contoh dapat dipelajari tanpa konfigurasi editor khusus; terminal tetap menjadi acuan untuk melihat perintah yang dijalankan.
rustup component add rustfmt clippy
Rustfmt dan Clippy merupakan alat pemformatan serta lint untuk Rust. Rujukan penggunaannya tersedia pada Rustfmt (diakses 2026/10), README dan Clippy (diakses 2026/10), Usage. Keduanya membantu pemeriksaan kode, tetapi tidak membuktikan semua kebutuhan aplikasi sudah terpenuhi.
4. Cara memakai folder contoh dalam ZIP
Setelah mengekstrak paket, buka terminal pada folder kode/dasar. Folder ini berisi satu package Cargo dengan 20 contoh di direktori examples/. Contoh dijalankan satu per satu; Anda tidak perlu menyalin semua fungsi main ke file yang sama. Cargo mendukung target examples melalui opsi --example. Cargo Build (diakses 2026/10), Target Selection.
cd kode/dasar
cargo run --example 01_halo
cargo run --example 02_variabel
Manifest contoh dasar:
[package]
name = "rust-dasar-tumbas"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
Untuk memulai proyek baru sendiri, gunakan alur Cargo berikut pada folder kerja pilihan Anda:
cargo new latihan_rust
cd latihan_rust
cargo run
cargo check
cargo build --release
Cargo mengelola build dan dependensi. cargo check memeriksa program tanpa menghasilkan executable akhir; build release menggunakan profil release. Sumber dan pengaturan proyek tetap perlu Anda pahami, karena hasil kompilasi tidak menguji kebenaran seluruh logika bisnis. Rust Hello Cargo (diakses 2026/10), Building and Running.

Diagram editorial: beberapa perintah Cargo yang dipakai dalam panduan. Panah menunjukkan alur kerja belajar, bukan urutan wajib untuk setiap perubahan.
5. Contoh 1–4: dasar sintaks dan alur program
Contoh 1. Menampilkan teks
File kode/dasar/examples/01_halo.rs:
fn main() {
println!("Halo, Rust!");
}
Jalankan dari kode/dasar:
cargo run --example 01_halo
Keluaran yang diharapkan:
Halo, Rust!
main merupakan titik masuk program, sedangkan println! digunakan untuk mencetak keluaran. Tanda seru menunjukkan pemanggilan macro. Untuk tahap pertama, ubah teksnya dan jalankan ulang supaya Anda melihat hubungan antara file sumber dan hasil program. Rust Functions (diakses 2026/10), pengantar; Rust println (diakses 2026/10), macro.
Contoh 2. Variabel dan mutabilitas
fn main() {
let nama = "Buku";
let mut stok: u32 = 3;
stok += 2;
let harga: u64 = 25_000;
println!("{nama}: stok {stok}, harga Rp{harga}");
}
Jalankan dari kode/dasar:
cargo run --example 02_variabel
Keluaran yang diharapkan:
Buku: stok 5, harga Rp25000
Binding Rust secara default immutable. mut mengizinkan perubahan nilai binding. Pada contoh ini, stok berubah dari tiga menjadi lima, sementara nama dan harga tidak diubah. Underscore dalam literal angka digunakan agar angka lebih mudah dibaca. Rust Variables (diakses 2026/10), Variables and Mutability; Rust Data Types (diakses 2026/10), Integer Literals.
Latihan: hilangkan mut lalu perhatikan pesan compiler. Setelah memahami sebabnya, kembalikan kode ke bentuk semula. Jangan mengatasi pesan tersebut dengan mengubah semua variabel menjadi mutable; tentukan dahulu nilai mana yang memang perlu berubah.
Contoh 3. Fungsi dengan nilai kembali
fn total(harga: u64, jumlah: u64) -> u64 {
harga * jumlah
}
fn main() {
println!("Total: {}", total(25_000, 2));
}
Jalankan dari kode/dasar:
cargo run --example 03_fungsi
Keluaran yang diharapkan:
Total: 50000
Ekspresi terakhir tanpa titik koma menjadi nilai kembali fungsi pada contoh ini. Parameter dan tipe hasil dituliskan agar kontrak fungsi jelas. Angka dalam latihan sengaja kecil; untuk input yang belum dapat dipercaya, perhatikan penanganan overflow pada contoh 9. Rust Functions (diakses 2026/10), Functions with Return Values.
Latihan: ubah jumlah menjadi tiga dan prediksi hasilnya sebelum menjalankan program. Kemudian jelaskan mengapa penambahan titik koma pada ekspresi terakhir dapat mengubah makna blok. Kebiasaan memprediksi hasil membantu Anda membaca kode secara aktif.
Contoh 4. Percabangan dan perulangan
fn main() {
for stok in [0, 2, 8] {
let status = if stok == 0 { "habis" } else { "tersedia" };
println!("{stok}: {status}");
}
}
Jalankan dari kode/dasar:
cargo run --example 04_kontrol
Keluaran yang diharapkan:
0: habis
2: tersedia
8: tersedia
Rust mempunyai ekspresi if dan perulangan for. Dalam contoh ini, setiap angka stok dipakai untuk menentukan teks status. Kita memakai for agar latihan tidak perlu mengelola indeks secara manual. Rust Control Flow (diakses 2026/10), if Expressions dan Looping.
Latihan: tambahkan status “menipis” untuk stok satu sampai tiga. Tuliskan urutan pemeriksaan kondisi sebelum mengubah program. Dengan begitu, Anda bisa menilai apakah hasil salah karena sintaks atau karena aturan yang disusun kurang tepat.
6. Contoh 5–8: ownership, borrowing, dan String

Ilustrasi ImageGen sebagai metafora ownership. Ilustrasi bukan model tata letak memori Rust.
Contoh 5. Memindahkan ownership
fn tampilkan(nama: String) {
println!("Pemilik baru: {nama}");
}
fn main() {
let nama = String::from("Buku Rust");
tampilkan(nama);
}
Jalankan dari kode/dasar:
cargo run --example 05_move
Keluaran yang diharapkan:
Pemilik baru: Buku Rust
Pada contoh ini, String diteruskan berdasarkan nilai kepada fungsi tampilkan. Ownership berpindah sehingga nama lama tidak dapat digunakan lagi sesudah pemindahan. Tidak semua tipe berperilaku sama: tipe yang mengimplementasikan Copy, seperti banyak tipe angka sederhana, dapat disalin. Rust Ownership (diakses 2026/10), Variables and Data Interacting with Move dan Copy.
Coba versi yang memang dibuat gagal pada kode/dasar/gagal-kompilasi/01_setelah_move.rs. File itu sengaja dipisahkan dari target Cargo agar tidak menggagalkan build contoh yang benar.
fn main() {
let awal = String::from("Buku");
let tujuan = awal;
println!("{awal} {tujuan}");
}
rustc --edition 2024 gagal-kompilasi/01_setelah_move.rs
Compiler diharapkan menolak pemakaian awal setelah move dengan kategori E0382. Rujukan penjelasannya tersedia pada Rust E0382 (diakses 2026/10). Perbaikan yang tepat bergantung pada tujuan: gunakan reference jika hanya membaca, atau salinan eksplisit jika memang membutuhkan data terpisah.
Contoh 6. Meminjam melalui reference
fn jumlah_huruf(teks: &str) -> usize {
teks.chars().count()
}
fn main() {
let nama = String::from("Buku");
println!("Huruf: {}", jumlah_huruf(&nama));
println!("Masih bisa dipakai: {nama}");
}
Jalankan dari kode/dasar:
cargo run --example 06_borrow
Keluaran yang diharapkan:
Huruf: 4
Masih bisa dipakai: Buku
Fungsi menerima &str, sehingga dapat membaca teks tanpa mengambil ownership String milik pemanggil. Sesudah fungsi selesai, variabel nama masih digunakan. Reference dan string slice dibahas pada Rust Borrowing (diakses 2026/10) serta Rust Slices (diakses 2026/10).
Jangan menyimpulkan setiap parameter wajib memakai reference. Tanyakan kebutuhan fungsi: apakah hanya membaca, mengubah, atau menyimpan data dengan ownership sendiri? Dalam latihan, ubah nama fungsi dan inputnya, tetapi pertahankan tujuan hanya membaca. Amati bahwa kontrak fungsi tetap sederhana.
Contoh 7. Mutable reference
fn tambah_stok(stok: &mut u32) {
*stok += 1;
}
fn main() {
let mut stok = 3;
tambah_stok(&mut stok);
println!("Stok: {stok}");
}
Jalankan dari kode/dasar:
cargo run --example 07_mut_borrow
Keluaran yang diharapkan:
Stok: 4
&mut memungkinkan fungsi mengubah nilai yang dipinjam. Aturan borrowing mencegah reference mutable yang bertumpang tindih dengan peminjaman lain yang masih digunakan. Batas peminjaman ditentukan dari penggunaan reference, sehingga jangan menyederhanakannya hanya sebagai seluruh blok kurung kurawal. Rust Borrowing (diakses 2026/10), Mutable References.
File 02_dua_mutable.rs menunjukkan kasus yang sengaja ditolak:
fn main() {
let mut teks = String::from("Rust");
let a = &mut teks;
let b = &mut teks;
a.push('!');
b.push('?');
}
rustc --edition 2024 gagal-kompilasi/02_dua_mutable.rs
Dua reference mutable tersebut sama-sama dipakai setelah dibuat. Compiler diharapkan menolak dengan kategori E0499. Latihan perbaikannya adalah menyelesaikan penggunaan reference pertama sebelum membuat dan memakai reference kedua. Rust E0499 (diakses 2026/10).

Diagram editorial: move memindahkan ownership pada contoh String; borrow mempertahankan ownership pada pemanggil. Diagram disederhanakan untuk latihan.
Contoh 8. String, byte, dan Unicode
fn main() {
let teks = String::from("café");
println!("Byte: {}", teks.len());
println!("Unicode scalar: {}", teks.chars().count());
println!("Huruf awal: {}", teks.chars().next().unwrap_or('?'));
}
Jalankan dari kode/dasar:
cargo run --example 08_unicode
Keluaran yang diharapkan:
Byte: 5
Unicode scalar: 4
Huruf awal: c
String menyimpan teks UTF-8. len() menghitung byte, sedangkan chars().count() menghitung Unicode scalar values. Keduanya tidak selalu sama, dan Unicode scalar tidak selalu sama dengan satu karakter yang tampak bagi pembaca. Rust Strings (diakses 2026/10), Bytes and Scalar Values and Grapheme Clusters.
Latihan: ganti teks dengan emoji dan teks yang memiliki tanda gabung. Catat hasilnya. Jangan memotong teks pengguna berdasarkan indeks byte sembarang. Untuk memulai, gunakan operasi string yang sesuai dan tentukan apakah kebutuhan Anda berbasis byte, scalar, atau tampilan karakter.
7. Contoh 9–14: data, kesalahan, dan koleksi
Contoh 9. Struct, method, dan perkalian yang diperiksa
struct Produk {
nama: String,
harga: u64,
}
impl Produk {
fn total(&self, jumlah: u64) -> Option<u64> {
self.harga.checked_mul(jumlah)
}
}
fn main() {
let produk = Produk {
nama: "Buku".into(),
harga: 25_000,
};
match produk.total(2) {
Some(total) => println!("{}: Rp{total}", produk.nama),
None => println!("Nilai terlalu besar"),
}
}
Jalankan dari kode/dasar:
cargo run --example 09_struct
Keluaran yang diharapkan:
Buku: Rp50000
Method didefinisikan dalam blok impl; &self meminjam instance untuk membaca datanya. checked_mul mengembalikan Option, sehingga contoh dapat membedakan hasil yang valid dari overflow. Rust Methods (diakses 2026/10), Method Syntax; Rust u64 (diakses 2026/10), checked_mul.
Harga latihan memakai bilangan bulat rupiah agar contoh tidak memperkenalkan pembulatan pecahan. Ini pilihan desain tutorial, bukan aturan umum sistem pembayaran. Jika mengembangkan aplikasi keuangan, tentukan mata uang, satuan, batas angka, pajak, dan kebijakan pembulatannya secara terpisah sebelum memilih representasi data.
Contoh 10. Nilai yang mungkin tidak ada dengan Option
fn main() {
let stok = [3, 7];
match stok.get(5) {
Some(nilai) => println!("Stok: {nilai}"),
None => println!("Data tidak ditemukan"),
}
}
Jalankan dari kode/dasar:
cargo run --example 10_option
Keluaran yang diharapkan:
Data tidak ditemukan
Option<T> mempunyai varian Some(T) dan None. Mengakses koleksi melalui get memungkinkan program menangani indeks yang tidak ditemukan tanpa langsung mengakses indeks tersebut. Rust Enum (diakses 2026/10), Option; Rust Vectors (diakses 2026/10), Reading Elements.
Latihan: ubah indeks lima menjadi satu. Perhatikan perbedaan antara data tidak ditemukan dan nilai data yang kebetulan nol. Jangan mengganti keduanya dengan angka bawaan yang sama bila aplikasi perlu membedakan kedua keadaan tersebut.
Contoh 11. Result dan operator tanda tanya
fn baca_jumlah(teks: &str) -> Result<u32, String> {
let jumlah = teks
.parse::<u32>()
.map_err(|_| "Harus bilangan bulat".to_string())?;
if jumlah == 0 {
return Err("Jumlah harus lebih dari nol".to_string());
}
Ok(jumlah)
}
fn main() {
for input in ["2", "0", "dua"] {
match baca_jumlah(input) {
Ok(n) => println!("OK: {n}"),
Err(e) => println!("Gagal: {e}"),
}
}
}
Jalankan dari kode/dasar:
cargo run --example 11_result
Keluaran yang diharapkan:
OK: 2
Gagal: Jumlah harus lebih dari nol
Gagal: Harus bilangan bulat
Result memakai Ok untuk sukses dan Err untuk kesalahan. Pada fungsi ini, map_err mengubah bentuk pesan error, kemudian ? meneruskan kesalahan kepada pemanggil. Validasi nilai nol adalah aturan contoh yang ditambahkan setelah konversi berhasil. Rust Result (diakses 2026/10), Propagating Errors.
Latihan: tambahkan batas jumlah maksimum seratus. Pastikan input “dua”, nol, dan seratus satu menghasilkan alasan yang sesuai. Hindari unwrap() pada input pengguna hanya untuk menghilangkan pesan compiler; tetapkan lebih dahulu respons yang masuk akal ketika konversi gagal.
Contoh 12. Vector untuk daftar yang berkembang
fn main() {
let mut stok = vec![3, 7, 0];
stok.push(4);
for nilai in &mut stok {
*nilai += 1;
}
println!("{stok:?}");
}
Jalankan dari kode/dasar:
cargo run --example 12_vec
Keluaran yang diharapkan:
[4, 8, 1, 5]
Vec<T> menyimpan daftar elemen bertipe sama. Contoh meminjam setiap elemen secara mutable untuk menambahkan satu. push dilakukan sebelum perulangan peminjaman, sehingga perubahan bentuk koleksi tidak dicampur dengan penggunaan reference terhadap elemennya. Rust Vectors (diakses 2026/10), Updating dan Iterating.
Latihan: tulis ulang penambahan stok menggunakan fungsi dari contoh tujuh. Kemudian pikirkan apa yang terjadi jika nilai berada di batas maksimum tipenya. Pertanyaan tersebut menghubungkan latihan koleksi dengan keputusan validasi yang sudah dipelajari.
Contoh 13. HashMap untuk menghitung kata
use std::collections::HashMap;
fn main() {
let mut hitung = HashMap::new();
for kata in "rust aman rust cepat".split_whitespace() {
*hitung.entry(kata).or_insert(0_u32) += 1;
}
let mut hasil: Vec<_> = hitung.into_iter().collect();
hasil.sort_by_key(|(kata, _)| *kata);
for (kata, jumlah) in hasil {
println!("{kata}: {jumlah}");
}
}
Jalankan dari kode/dasar:
cargo run --example 13_hashmap
Keluaran yang diharapkan:
aman: 1
cepat: 1
rust: 2
entry dan or_insert membantu memperbarui nilai untuk kunci yang sudah atau belum ada. Keluaran HashMap tidak menjanjikan urutan alfabet; contoh memindahkan pasangan ke vector lalu mengurutkannya sebelum mencetak. Rust HashMap (diakses 2026/10), entry dan Iteration.
Penghitung ini adalah latihan token yang dipisahkan whitespace. Ia tidak menghapus tanda baca atau menyamakan huruf besar. Jika dipakai untuk analisis dokumen, tulis aturan normalisasi yang diinginkan dan uji terlebih dahulu. Kata “Rust” dan “rust” dapat sengaja dianggap berbeda atau sama, bergantung kebutuhan.
Contoh 14. Iterator dan closure
fn main() {
let harga = [10_000_u64, 25_000, 50_000];
let terjangkau: Vec<_> = harga.iter().copied().filter(|h| *h <= 25_000).collect();
let total: u64 = terjangkau.iter().sum();
println!("Pilihan: {terjangkau:?}");
println!("Total: {total}");
}
Jalankan dari kode/dasar:
cargo run --example 14_iterator
Keluaran yang diharapkan:
Pilihan: [10000, 25000]
Total: 35000
Iterator Rust bersifat lazy; operasi perlu dikonsumsi agar menghasilkan pekerjaan yang diinginkan. Dalam contoh ini, collect membentuk vector dan sum menghasilkan total. Closure pada filter menyatakan syarat pemilihan harga. Rust Iterators (diakses 2026/10), pengantar dan Consuming Adaptors.
Latihan: tulis versi for yang menghasilkan keluaran sama, lalu bandingkan keterbacaannya. Tidak ada kewajiban membuat semua operasi menjadi rangkaian iterator panjang. Pilih bentuk yang dapat Anda jelaskan dan yang memudahkan pemeriksaan kesalahan.
8. Contoh 15–20: trait, generic, lifetime, file, thread, dan test
Contoh 15. Trait untuk perilaku bersama
trait Ringkas {
fn ringkas(&self) -> String;
}
struct Artikel {
judul: String,
}
impl Ringkas for Artikel {
fn ringkas(&self) -> String {
format!("Artikel: {}", self.judul)
}
}
fn cetak(item: &impl Ringkas) {
println!("{}", item.ringkas());
}
fn main() {
cetak(&Artikel {
judul: "Belajar Rust".into(),
});
}
Jalankan dari kode/dasar:
cargo run --example 15_trait
Keluaran yang diharapkan:
Artikel: Belajar Rust
Trait menyatakan perilaku yang dapat diterapkan tipe. Fungsi cetak menerima nilai yang memiliki perilaku Ringkas melalui reference. Trait tidak membuat Artikel mewarisi seluruh data dari tipe lain. Rust Traits (diakses 2026/10), Defining Shared Behavior.
Latihan: buat tipe Produk dengan method trait yang mengembalikan ringkasan namanya. Tujuannya melihat bagaimana dua bentuk data dapat menyediakan satu perilaku yang sama. Tunda trait yang rumit sampai Anda mempunyai kebutuhan penggunaan ulang yang jelas.
Contoh 16. Generic lintas tipe
fn pertama<T>(data: &[T]) -> Option<&T> {
data.first()
}
fn main() {
println!("Angka: {:?}", pertama(&[10, 20]));
println!("Teks: {:?}", pertama(&["Rust", "Go"]));
}
Jalankan dari kode/dasar:
cargo run --example 16_generic
Keluaran yang diharapkan:
Angka: Some(10)
Teks: Some("Rust")
Fungsi pertama bekerja terhadap slice bertipe T, lalu mengembalikan Option<&T>. Contoh ini tidak memerlukan batas trait tambahan karena hanya mengambil elemen pertama, bukan membandingkan atau mencetak T di dalam fungsi. Dasar generic dibahas pada Rust Generics (diakses 2026/10), Generic Data Types.
Latihan: panggil fungsi dengan slice kosong yang tipenya jelas, misalnya &[] as &[i32]. Prediksi hasilnya. Setelah itu, pikirkan perbedaan antara mengembalikan reference elemen dan membuat salinan elemen yang dimiliki pemanggil.
Contoh 17. Lifetime menyatakan hubungan reference
fn pilih_panjang<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() >= b.len() { a } else { b }
}
fn main() {
let a = String::from("Rust");
let b = String::from("Belajar");
println!("Pilihan: {}", pilih_panjang(&a, &b));
}
Jalankan dari kode/dasar:
cargo run --example 17_lifetime
Keluaran yang diharapkan:
Pilihan: Belajar
Anotasi 'a menghubungkan masa berlaku reference input dan hasil. Ia tidak memperpanjang hidup data. Fungsi memilih salah satu input, sehingga hasil harus tetap valid pada penggunaan yang diizinkan pemanggil. Pemilihan panjang di sini berdasarkan byte, mengikuti len(). Rust Lifetimes (diakses 2026/10), Lifetime Annotation Syntax.
Contoh gagal pada file 03_reference_lokal.rs mencoba mengembalikan reference ke String lokal:
fn salah() -> &'static str {
let teks = String::from("Rust");
&teks
}
fn main() { println!("{}", salah()); }
rustc --edition 2024 gagal-kompilasi/03_reference_lokal.rs
Compiler diharapkan menolak dengan E0515. Menambahkan 'static pada tanda tangan fungsi tidak mengubah data lokal menjadi hidup selamanya. Salah satu perbaikan untuk kebutuhan seperti ini adalah mengembalikan String yang dimiliki hasil fungsi. Rust E0515 (diakses 2026/10).
Contoh 18. Membaca berkas teks
use std::{fs, io};
fn main() -> io::Result<()> {
let isi = fs::read_to_string("data/contoh.txt")?;
println!("Baris: {}", isi.lines().count());
Ok(())
}
Jalankan dari kode/dasar:
cargo run --example 18_file
Keluaran yang diharapkan:
Baris: 3
Jalankan contoh dari folder kode/dasar, karena path berkas bersifat relatif terhadap direktori kerja program. read_to_string membaca isi berkas menjadi String dan mengembalikan error untuk kegagalan pembacaan atau data yang bukan UTF-8 valid. Rust read_to_string (diakses 2026/10), Errors.
Contoh kecil ini membaca seluruh isi. Pada proyek CLI, kita menambahkan batas ukuran untuk latihan yang menerima path dari pengguna. Untuk aplikasi produksi, tentukan kebutuhan ukuran dan pola streaming berdasarkan jenis berkas yang benar-benar diolah.
Contoh 19. Thread dan pemindahan data
use std::thread;
fn main() {
let mut angka = vec![1_u64, 2];
angka.push(3);
let pekerja = thread::spawn(move || angka.iter().sum::<u64>());
match pekerja.join() {
Ok(total) => println!("Total thread: {total}"),
Err(_) => eprintln!("Thread gagal"),
}
}
Jalankan dari kode/dasar:
cargo run --example 19_thread
Keluaran yang diharapkan:
Total thread: 6
Closure move mengambil ownership data yang dipakai thread. join menunggu thread selesai dan memberikan hasil yang dapat diperiksa. Rust membantu sejumlah aspek keselamatan, tetapi program concurrent masih perlu dirancang untuk menghindari deadlock dan masalah urutan operasi. Rust Threads (diakses 2026/10), spawn dan join.
Jangan memakai contoh ini sebagai bukti bahwa menambah thread selalu mempercepat program. Data latihan terlalu kecil untuk penilaian performa. Gunakan latihan untuk memahami pemindahan ownership dan hasil pekerjaan sebelum mencoba koordinasi antarthread yang lebih rumit.
Contoh 20. Module dan unit test
mod validasi {
pub fn nama_valid(nama: &str) -> bool {
!nama.trim().is_empty() && nama.chars().count() <= 40
}
}
fn main() {
println!("Nama valid: {}", validasi::nama_valid("Buku"));
}
#[cfg(test)]
mod tests {
use super::validasi::nama_valid;
#[test]
fn menolak_nama_kosong() {
assert!(!nama_valid(" "));
}
#[test]
fn menerima_nama_wajar() {
assert!(nama_valid("Buku"));
}
}
Jalankan dari kode/dasar:
cargo run --example 20_modul
Keluaran yang diharapkan:
Nama valid: true
cargo test --example 20_modul
Atribut #[test] menandai fungsi pengujian; assertion memeriksa hasil yang diharapkan. Module membantu mengelompokkan kode dan mengatur visibilitas. Rust Tests (diakses 2026/10), Structuring Test Functions; Rust Modules (diakses 2026/10), Defining Modules.
Tambahkan sendiri kasus nama terlalu panjang. Itu menguji aturan yang berbeda dari kasus kosong. Jika aturan berubah, perbarui alasan dan perilaku yang diharapkan, lalu ubah implementasinya. Jangan hanya mengganti nilai assertion agar hasil test kembali hijau.
9. Proyek pertama: alat pencarian teks lewat terminal

Ilustrasi ImageGen: proyek CLI pencarian dokumen. Program latihan membaca berkas teks lokal.
Proyek cari-teks menyatukan argumen terminal, validasi, pembacaan berkas, lifetime hasil pencarian, dan penanganan error. Kita memilih pencarian substring yang peka huruf besar, mempertahankan nomor baris, serta membatasi pembacaan sampai 2 MiB. Semua ini merupakan keputusan desain contoh, bukan perilaku bawaan seluruh aplikasi Rust.
Struktur dan manifest
Buka folder kode/cari-teks. src/lib.rs berisi fungsi yang dapat diuji, src/main.rs mengatur input dan exit code, dan fixtures/catatan.txt menyediakan data contoh. Pemisahan library dan binary memudahkan kita menguji logika tanpa harus selalu menjalankan terminal secara manual.
[package]
name = "cari-teks"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
Kode library lengkap
use std::{
fs::File,
io::{self, Read},
path::PathBuf,
};
pub const BATAS_BYTE: u64 = 2 * 1024 * 1024;
#[derive(Debug)]
pub struct Config {
pub kata: String,
pub path: PathBuf,
}
impl Config {
pub fn parse(args: impl IntoIterator<Item = String>) -> Result<Self, String> {
let args: Vec<String> = args.into_iter().collect();
if args.len() != 2 {
return Err("Gunakan: cari-teks <kata> <path>".into());
}
if args[0].trim().is_empty() {
return Err("Kata pencarian tidak boleh kosong".into());
}
Ok(Self {
kata: args[0].clone(),
path: PathBuf::from(&args[1]),
})
}
}
pub fn baca_terbatas(path: &std::path::Path) -> io::Result<String> {
let file = File::open(path)?;
let mut isi = String::new();
file.take(BATAS_BYTE + 1).read_to_string(&mut isi)?;
if isi.len() as u64 > BATAS_BYTE {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Berkas melebihi 2 MiB",
));
}
Ok(isi)
}
pub fn cari<'a>(kata: &str, isi: &'a str) -> Vec<(usize, &'a str)> {
isi.lines()
.enumerate()
.filter(|(_, baris)| baris.contains(kata))
.map(|(i, baris)| (i + 1, baris))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn menemukan_dan_menyimpan_nomor_baris() {
assert_eq!(
cari("Rust", "Satu\nRust aman\nTiga"),
vec![(2, "Rust aman")]
);
}
#[test]
fn tidak_ada_kecocokan() {
assert!(cari("Go", "Rust").is_empty());
}
#[test]
fn peka_huruf_besar() {
assert!(cari("rust", "Rust").is_empty());
}
#[test]
fn mendukung_unicode_dan_crlf() {
assert_eq!(
cari("café", "café lokal\r\nselesai"),
vec![(1, "café lokal")]
);
}
#[test]
fn menolak_kata_kosong() {
assert!(Config::parse([" ".into(), "contoh.txt".into()]).is_err());
}
#[test]
fn menolak_jumlah_argumen_salah() {
assert!(Config::parse(["Rust".into()]).is_err());
}
}
Fungsi baca_terbatas membaca paling banyak batas ditambah satu byte agar kelebihan ukuran dapat dideteksi. Untuk berkas besar, pembacaan berhenti tanpa mengambil seluruh isinya. Apabila potongan yang dibaca tidak membentuk UTF-8 valid, fungsi dapat mengembalikan error UTF-8 sebelum pesan ukuran khusus. Itu tetap kegagalan yang perlu ditampilkan secara wajar kepada pengguna. Mekanisme take didokumentasikan pada Rust Read (diakses 2026/10), take.
Fungsi cari mengembalikan reference ke baris dalam isi. Karena itu hasil tidak memiliki salinan teks sendiri dan tidak boleh dipakai setelah sumber teksnya tidak lagi valid. Anotasi lifetime menyatakan hubungan tersebut; desain ini sengaja menghubungkan proyek dengan contoh 17.
Kode program utama lengkap
use cari_teks::{Config, baca_terbatas, cari};
use std::{env, process::ExitCode};
fn main() -> ExitCode {
let config = match Config::parse(env::args().skip(1)) {
Ok(c) => c,
Err(e) => {
eprintln!("{e}");
return ExitCode::from(2);
}
};
let isi = match baca_terbatas(&config.path) {
Ok(s) => s,
Err(e) => {
eprintln!("Gagal membaca: {e}");
return ExitCode::from(2);
}
};
let hasil = cari(&config.kata, &isi);
if hasil.is_empty() {
return ExitCode::from(1);
}
for (nomor, baris) in hasil {
println!("{nomor}:{baris}");
}
ExitCode::SUCCESS
}
Kontrak exit code proyek ini adalah nol jika ada hasil, satu jika tidak ada kecocokan, dan dua jika argumen atau pembacaan gagal. Ini konvensi contoh yang dapat Anda gunakan untuk memeriksa hasil dari shell. Program tidak mengedit berkas input.
Menjalankan proyek
Dari folder kode/cari-teks:
cargo run -- Rust fixtures/catatan.txt
Keluaran yang diharapkan:
1:Belajar Rust dari dasar.
3:Rust memiliki ownership.
Coba pencarian tanpa hasil:
cargo run -- Java fixtures/catatan.txt
Program tidak mencetak baris hasil dan memberikan exit code satu. Di PowerShell, periksa $LASTEXITCODE segera sesudah perintah; di shell Unix, gunakan echo $?. Untuk pencarian kata yang mengandung spasi, gunakan tanda kutip agar tetap diterima sebagai satu argumen.
cargo run -- "Belajar Rust" fixtures/catatan.txt
$LASTEXITCODE
Jangan mencampur keluaran Cargo seperti pesan kompilasi dengan keluaran program. Untuk pemakaian berulang, Anda dapat membangun executable lalu menjalankannya langsung. Nama berkas executable dan kesesuaian target bergantung sistem operasi; lihat bagian build dan deployment.
Menguji perilaku CLI
cargo test --offline
Kode library mencakup kasus pencarian berhasil, tidak ditemukan, peka huruf besar, Unicode/CRLF, serta argumen tidak sah. File tests/cli.rs menambahkan pengujian proses untuk exit code dan keluaran aktual:
use std::{path::PathBuf, process::Command};
fn fixture() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fixtures/catatan.txt")
}
#[test]
fn sukses_dengan_nomor_baris() {
let out = Command::new(env!("CARGO_BIN_EXE_cari-teks"))
.arg("Rust")
.arg(fixture())
.output()
.unwrap();
assert_eq!(out.status.code(), Some(0));
assert_eq!(
String::from_utf8(out.stdout).unwrap(),
"1:Belajar Rust dari dasar.\n3:Rust memiliki ownership.\n"
);
}
#[test]
fn hasil_kosong_memakai_kode_satu() {
let out = Command::new(env!("CARGO_BIN_EXE_cari-teks"))
.arg("Java")
.arg(fixture())
.output()
.unwrap();
assert_eq!(out.status.code(), Some(1));
assert!(out.stdout.is_empty());
}
#[test]
fn argumen_salah_memakai_kode_dua() {
let out = Command::new(env!("CARGO_BIN_EXE_cari-teks"))
.output()
.unwrap();
assert_eq!(out.status.code(), Some(2));
assert!(!out.stderr.is_empty());
}
#[test]
fn berkas_hilang_memakai_kode_dua() {
let hilang = fixture().join("tidak-ada.txt");
let out = Command::new(env!("CARGO_BIN_EXE_cari-teks"))
.arg("Rust")
.arg(hilang)
.output()
.unwrap();
assert_eq!(out.status.code(), Some(2));
}
#[test]
fn menolak_berkas_besar() {
let path = std::env::temp_dir().join(format!("rust-tumbas-{}-besar.txt", std::process::id()));
std::fs::write(&path, vec![b'a'; cari_teks::BATAS_BYTE as usize + 1]).unwrap();
let hasil = cari_teks::baca_terbatas(&path);
std::fs::remove_file(&path).unwrap();
assert!(hasil.unwrap_err().to_string().contains("2 MiB"));
}
#[test]
fn menolak_utf8_tidak_valid() {
let path = std::env::temp_dir().join(format!("rust-tumbas-{}-utf8.txt", std::process::id()));
std::fs::write(&path, [0xff, 0xfe]).unwrap();
let hasil = cari_teks::baca_terbatas(&path);
std::fs::remove_file(&path).unwrap();
assert!(hasil.is_err());
}
Test bukan klaim bahwa program telah menangani seluruh kondisi sistem berkas. Versi latihan juga memakai env::args, sehingga argumen OS yang tidak dapat dikonversi menjadi Unicode tidak ditangani secara khusus. Jika membutuhkan nama berkas non-Unicode, pertimbangkan desain argumen berbasis args_os dan OsString. Rust env args (diakses 2026/10), Panics.
10. Proyek kedua: API katalog dengan Axum

Ilustrasi ImageGen: layanan API latihan di komputer lokal. Panel layar bukan tangkapan hasil eksekusi.
Proyek API menyajikan katalog statis dengan dua produk buatan. Tidak ada database, autentikasi, unggah berkas, atau perubahan data. Kita sengaja membatasi lingkup agar dapat mempelajari routing, parameter, query, JSON, dan status HTTP tanpa tambahan kebutuhan aplikasi bisnis.
Dependensi dan perannya
Axum menangani route dan extractor. Tokio menjalankan kode async. Serde menyediakan implementasi serialisasi/deserialisasi melalui derive. Router contoh menggunakan sintaks parameter /{id} pada jalur Axum 0.8. Axum (diakses 2026/10), Routing dan Extractors; Tokio (diakses 2026/10), Runtime; Serde Derive (diakses 2026/10).
Manifest berada di kode/api-katalog/Cargo.toml:
[package]
name = "api-katalog"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
axum = "0.8"
tokio = { version = "1", features = ["macros", "rt-multi-thread", "net", "signal"] }
serde = { version = "1", features = ["derive"] }
[dev-dependencies]
tower = { version = "0.5", features = ["util"] }
serde_json = "1"
Rentang versi dalam manifest bukan klaim bahwa patch baru sudah diuji. Cargo.lock dalam paket mencatat versi hasil resolusi saat pengujian. Untuk mengulang build dengan pilihan versi yang sama, pertahankan lockfile dan gunakan --locked. Pengunduhan dependensi pertama tetap membutuhkan jaringan jika cache belum tersedia. Cargo Lockfile (diakses 2026/10), Cargo.toml versus Cargo.lock.
Library API lengkap
use axum::{
Json, Router,
extract::{Path, Query},
http::StatusCode,
routing::get,
};
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct Produk {
id: u32,
nama: &'static str,
harga: u64,
}
#[derive(Deserialize)]
struct Filter {
q: Option<String>,
}
#[derive(Serialize)]
struct Pesan {
pesan: &'static str,
}
type ApiError = (StatusCode, Json<Pesan>);
fn produk() -> Vec<Produk> {
vec![
Produk {
id: 1,
nama: "Buku Rust",
harga: 75_000,
},
Produk {
id: 2,
nama: "Buku Python",
harga: 65_000,
},
]
}
async fn sehat() -> Json<Pesan> {
Json(Pesan { pesan: "ok" })
}
async fn daftar(Query(filter): Query<Filter>) -> Result<Json<Vec<Produk>>, ApiError> {
let q = filter.q.unwrap_or_default();
if q.chars().count() > 64 {
return Err((
StatusCode::BAD_REQUEST,
Json(Pesan {
pesan: "q maksimal 64 Unicode scalar",
}),
));
}
let q = q.to_lowercase();
let hasil = produk()
.into_iter()
.filter(|p| p.nama.to_lowercase().contains(&q))
.collect();
Ok(Json(hasil))
}
async fn detail(Path(id): Path<u32>) -> Result<Json<Produk>, ApiError> {
produk().into_iter().find(|p| p.id == id).map(Json).ok_or((
StatusCode::NOT_FOUND,
Json(Pesan {
pesan: "Produk tidak ditemukan",
}),
))
}
async fn tidak_ada() -> ApiError {
(
StatusCode::NOT_FOUND,
Json(Pesan {
pesan: "Rute tidak ditemukan",
}),
)
}
pub fn app() -> Router {
Router::new()
.route("/health", get(sehat))
.route("/produk", get(daftar))
.route("/produk/{id}", get(detail))
.fallback(tidak_ada)
}
Parameter q diperlakukan sebagai pencarian substring tanpa membedakan huruf besar setelah konversi sederhana to_lowercase. Ini belum menjadi pencarian linguistik atau normalisasi Unicode lengkap. Batas 64 dihitung menggunakan Unicode scalar values, bukan grapheme cluster. Batas ini memeriksa nilai setelah query diekstrak; jangan menafsirkannya sebagai batas panjang seluruh request pada server.
Route detail memakai Path<u32>. ID yang bukan angka ditolak extractor. Respons error yang dibuat handler kita menggunakan JSON, tetapi rejection bawaan extractor dan metode HTTP yang tidak didukung dapat memiliki bentuk berbeda. Jika mengembangkan kontrak API produksi, tentukan kebijakan respons error lalu tangani rejection secara konsisten. Axum (diakses 2026/10), Extractors dan Responses.
Program server lengkap
#[tokio::main]
async fn main() -> std::io::Result<()> {
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?;
println!("API latihan: http://127.0.0.1:3000");
axum::serve(listener, api_katalog::app())
.with_graceful_shutdown(async {
if let Err(e) = tokio::signal::ctrl_c().await {
eprintln!("Gagal memasang handler Ctrl+C: {e}");
}
})
.await
}
Alamat bind adalah 127.0.0.1:3000, sehingga contoh ditujukan untuk akses loopback lokal. Handler shutdown menunggu Ctrl+C. Jangan mengubah bind menjadi alamat publik sebelum menyiapkan kebutuhan pengoperasian, batas request, dan kebijakan akses yang sesuai aplikasi.
Menjalankan dan mencoba endpoint
Dari folder kode/api-katalog, jalankan:
cargo run --locked
Buka terminal kedua. Pada PowerShell:
Invoke-RestMethod "http://127.0.0.1:3000/health"
Invoke-RestMethod "http://127.0.0.1:3000/produk?q=rust"
Invoke-RestMethod "http://127.0.0.1:3000/produk/1"
Pada Linux, macOS, atau Windows yang menyediakan executable curl, gunakan:
curl -i "http://127.0.0.1:3000/health"
curl -i "http://127.0.0.1:3000/produk?q=rust"
curl -i "http://127.0.0.1:3000/produk/99"
Pada Windows, gunakan curl.exe bila nama curl di shell Anda mengarah ke perintah lain. Perhatikan status dan body, bukan hanya bahwa browser menampilkan sesuatu.
| Permintaan | Hasil yang diharapkan dari proyek ini |
|---|---|
GET /health |
200 dan JSON pesan ok |
GET /produk |
200 dan daftar dua produk |
GET /produk?q=rust |
200 dan daftar satu produk |
GET /produk/1 |
200 dan objek produk pertama |
GET /produk/99 |
404 dan JSON produk tidak ditemukan |
GET /produk/abc |
400 dari extractor path |
GET /rahasia |
404 dari fallback aplikasi |
POST /produk |
405 karena metode tidak didukung |
Test HTTP tanpa membuka port
Pengujian dalam kode/api-katalog/tests/http.rs memanggil router melalui oneshot. Cara ini memeriksa handler dan respons di dalam proses; ia tidak menggantikan pemeriksaan jaringan, proxy, TLS, atau izin firewall. Pemakaian ServiceExt::oneshot mengikuti fasilitas Tower ServiceExt (diakses 2026/10), oneshot.
cargo test --locked
Kode test lengkap ikut dalam ZIP. Ada tujuh kasus: health, filter, ID hilang, query terlalu panjang, ID bukan angka, rute hilang, dan metode salah. Untuk menambah cakupan sendiri, periksa daftar tanpa filter dan hasil filter kosong. Tentukan output yang diharapkan sebelum menambah handler baru.
11. Async bukan izin untuk menjalankan semua pekerjaan secara serentak
Tokio menjalankan tugas asinkron dan menyediakan mekanisme untuk pekerjaan blocking. Dokumentasinya membedakan tugas yang menunggu I/O dari pekerjaan yang lama memakai CPU atau memblokir thread. Karena itu, jangan menaruh pekerjaan berat langsung pada handler async tanpa menilai dampaknya terhadap tugas lain. Tokio (diakses 2026/10), CPU-bound tasks and blocking code.
Untuk latihan lanjutan, buat simulasi pekerjaan yang lambat pada proyek terpisah dan amati waktu respons. Jangan menambahkan simulasi lambat ke endpoint yang dipakai orang lain. Sebelum memilih pembatasan concurrency, tuliskan berapa pekerjaan yang boleh berjalan, berapa lama pengguna boleh menunggu, dan bagaimana pembatalan ditangani.
Saran editorial kami adalah menunda antrean, cache, dan banyak layanan sampai kontrak API kecil sudah stabil. Setiap komponen baru sebaiknya menjawab masalah yang dapat Anda tunjukkan. Jika masalahnya belum terlihat, simpan sebagai topik belajar berikutnya.
12. Keamanan Rust: bedakan memori, akses, dan operasi aplikasi
Rust memeriksa aturan memori dalam safe code, sedangkan unsafe membuka operasi tertentu dengan persyaratan yang harus dipenuhi penulis. unsafe juga tidak mematikan seluruh pemeriksaan compiler. Rust Unsafe (diakses 2026/10), Performing Unsafe Superpowers.
Sebagai saran evaluasi proyek, pisahkan pertanyaan keselamatan memori dari izin aplikasi. Misalnya, handler dapat berhasil mengembalikan objek JSON tetapi rancangan Anda belum menjawab apakah peminta boleh membaca objek itu. Pada API latihan, katalog sengaja bersifat publik dan statis; jangan memindahkan pola itu langsung ke dokumen pribadi.
Sebelum proyek dikembangkan untuk data nyata, tulis kebutuhan berikut: identitas pengguna, izin per tindakan, batas input, perlindungan rahasia, log yang diperlukan, proses pembaruan dependensi, cadangan, serta prosedur pemulihan. Ini daftar rancangan editorial untuk membantu pembelajaran, bukan hasil audit atau jaminan keamanan.
Untuk inspirasi proyek setelah menyelesaikan latihan, Anda dapat membaca 100 Proyek GitHub Pengganti Software Berbayar di Tumbas.in. Gunakan bacaan internal itu untuk mengenali kebutuhan aplikasi, lalu periksa dokumentasi proyek aslinya sebelum mengadopsi kode atau dependensi.
13. Build, executable, dan pertanyaan tentang hosting
cargo build --release --locked
Cargo menempatkan hasil build pada direktori target untuk profil dan target yang dipakai. Build release tidak otomatis berarti executable cocok untuk semua sistem operasi. Target kompilasi, pustaka native, dan cara linking perlu diperhatikan ketika memindahkan program. Cargo Build (diakses 2026/10), Compilation Options dan Output Options.
Untuk menjalankan CLI pada Windows, hasil binary umumnya memakai ekstensi .exe; pada Unix tidak memakai ekstensi tersebut. Gunakan hasil untuk sistem tujuan yang sesuai. Jika muncul kegagalan arsitektur atau pustaka runtime, catat target dan pesan error sebelum mencoba membangun ulang.
Jika hosting Anda masih shared hosting, tanyakan apakah paketnya mengizinkan executable, proses yang terus aktif, reverse proxy, dan pengaturan port. Jangan menyimpulkan dukungan Rust dari kemampuan mengunggah berkas atau dari adanya akses terminal saja. Jawaban harus berasal dari penyedia untuk paket yang digunakan.
Untuk proyek belajar, jalankan di komputer sendiri lebih dahulu. Server atau container menjadi topik berikutnya setelah Anda dapat memulai, menghentikan, memeriksa log, serta mengulang build proyek lokal. API dalam paket belum menyertakan konfigurasi publikasi produksi.
14. Troubleshooting yang sering ditemui
| Gejala | Pemeriksaan pertama | Tindakan latihan |
|---|---|---|
cargo tidak dikenali |
Instalasi Rustup dan PATH terminal | Buka terminal baru lalu cek versi |
| Linker tidak ditemukan | Pesan installer dan alat build OS | Pasang toolchain native yang diminta |
| E0382 setelah memakai String | Apakah ownership sudah berpindah? | Tinjau kebutuhan nilai atau reference |
| E0499 saat meminjam mutable | Apakah reference sebelumnya masih dipakai? | Selesaikan penggunaan pertama |
| E0515 pada return reference | Apakah hasil merujuk data lokal? | Pertimbangkan nilai yang dimiliki hasil |
| Contoh file gagal membaca | Direktori kerja dan path relatif | Jalankan dari kode/dasar |
| Unduhan crate gagal | Jaringan, proxy, cache, dan lockfile | Selesaikan pengunduhan sebelum offline |
| API gagal bind | Port 3000 sedang dipakai | Hentikan proses latihan lain atau pilih port |
| API memberi 400 pada ID | Tipe path u32 dan bentuk URL |
Coba ID angka dalam rentang yang valid |
| Hasil CLI kosong | Huruf besar dan kata pencarian | Coba Rust pada fixture yang disediakan |
Kategori error compiler pada tabel mengacu pada Rust E0382, Rust E0499, dan Rust E0515, diakses 2026/10. Pemeriksaan lingkungan lain adalah saran troubleshooting untuk contoh paket ini.
Ketika menemui pesan panjang, cari error pertama yang menunjuk kode Anda, perhatikan baris yang dirujuk, dan ubah satu hal dahulu. Simpan keluaran error sebelum perubahan agar Anda dapat membandingkan penyebabnya. Hindari mengganti versi banyak dependensi sekaligus hanya untuk menghilangkan satu pesan.
15. Format, lint, dan membaca hasil pengujian

Ilustrasi ImageGen: meninjau hasil pengujian. Keluaran aktual disertakan sebagai teks dalam paket.
Dari masing-masing proyek, gunakan perintah yang sesuai:
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
Untuk proyek API dengan lockfile, tambahkan --locked pada Clippy dan test. Pada contoh dasar dan CLI tanpa dependensi luar, Anda juga dapat menambahkan --offline. Mode offline memerlukan seluruh hal yang dibutuhkan build sudah tersedia secara lokal. Cargo Offline (diakses 2026/10), Network Options; Clippy Usage (diakses 2026/10).
Baca hasil uji dengan lingkupnya. Unit test memeriksa fungsi, test proses CLI memeriksa program terminal, test router memeriksa respons dalam proses, dan smoke test jaringan memeriksa server lokal benar-benar merespons. Tidak satu pun otomatis menjadi pengujian beban atau audit keamanan.
Pada penyiapan paket ini, contoh dikompilasi dan dijalankan pada rustc 1.99.1 (58cf8f9c3 2026-10-13) di Linux. Dua puluh contoh menghasilkan stdout yang cocok dengan keluaran di artikel. Tiga contoh yang sengaja salah ditolak dengan kategori error yang diharapkan. Sebanyak 21 test otomatis lolos: dua pada contoh module, dua belas pada proyek CLI, dan tujuh pada router API. Format, Clippy dengan warnings sebagai error, serta build release untuk ketiga proyek juga berhasil.
Server API lokal dijalankan sebagai proses dan diperiksa melalui sembilan permintaan HTTP, mencakup status 200, 400, 404, dan 405. Ini pemeriksaan fungsional kecil pada loopback, bukan uji beban, audit keamanan, atau verifikasi Windows/macOS. Test API offline dilakukan sesudah seluruh dependensi diunduh; cache dependensi tersebut tidak ikut dikemas. Log perintah dan hasil tersimpan di hasil-uji.txt dan hasil-uji.json.
Jika mengubah kode setelah mengekstrak paket, jalankan kembali pemeriksaan yang relevan. Cargo.lock membantu menjaga resolusi versi, tetapi tidak menjamin lingkungan operasi, jaringan, atau data pengguna sama dengan lingkungan penyiapan artikel.
16. Rencana belajar Rust selama empat minggu
Rencana berikut adalah usulan editorial yang boleh diperlambat sesuai waktu dan pengalaman. Tujuannya menghasilkan pemahaman yang dapat dijelaskan, bukan menjanjikan penguasaan Rust dalam 30 hari.
Minggu pertama: selesaikan contoh satu sampai delapan. Catat kapan nilai berpindah dan kapan dipinjam. Ubah input pada setiap contoh, prediksi hasil, lalu jalankan. Jika borrowing belum jelas, ulangi fungsi kecil sebelum berpindah ke framework web.
Minggu kedua: kerjakan contoh sembilan sampai dua puluh. Tambahkan satu aturan validasi pada Result, satu test pada module, dan satu koleksi dengan tipe berbeda. Pelajari pesan compiler yang muncul dari perubahan Anda sendiri.
Minggu ketiga: jalankan CLI, baca semua test, dan tambahkan fitur kecil seperti menampilkan jumlah baris yang cocok. Tentukan dahulu apakah pencarian tetap peka huruf besar. Jika menambah opsi, perbarui kontrak argumen dan test prosesnya.
Minggu keempat: jalankan API lokal, periksa status dan body, lalu tambahkan satu produk. Setelah itu, rancang satu fitur baru di atas kertas. Bila ingin database, tuliskan skema, aturan perubahan, dan pemulihannya sebelum memilih pustaka tambahan.
Simpan catatan satu halaman berisi cara menjalankan proyek, versi toolchain, perilaku yang sudah diuji, dan batas yang belum ditangani. Catatan tersebut akan lebih berguna saat kembali belajar daripada kumpulan perintah tanpa konteks.
17. FAQ belajar Rust
Apakah harus belajar C atau C++ lebih dahulu?
Jalur editorial panduan ini tidak mensyaratkannya. Anda dapat mulai dari fungsi dan data kecil, lalu mempelajari ownership secara bertahap. Jika istilah sistem terasa asing, perlambat bagian dasar dan gunakan contoh yang hasilnya dapat diperiksa.
Apakah Rust hanya untuk sistem operasi?
Tidak. Tokio menyediakan fondasi aplikasi jaringan dan Axum menyediakan penanganan HTTP. Panduan ini menunjukkan satu jalur backend melalui keduanya. Itu tidak berarti Rust wajib digunakan untuk setiap jenis website. Tokio Tutorial (diakses 2026/10); Axum (diakses 2026/10).
Mengapa compiler menolak kode yang terlihat masuk akal?
Rust memeriksa aturan yang harus dapat dibuktikan oleh compiler. Dokumentasi menjelaskan bahwa analisis statis bersifat konservatif; sebagian program yang mungkin benar tetap dapat ditolak jika persyaratan tidak dapat dibuktikan. Untuk belajar, pahami pesan error dan perbaiki struktur data atau reference sebelum mempertimbangkan unsafe. Rust Unsafe (diakses 2026/10), pengantar.
Apakah menambahkan clone selalu menyelesaikan ownership?
clone dapat membuat salinan data pada tipe yang mendukungnya; pada String, ia menyalin data heap. Namun, kebutuhan aplikasi belum tentu memerlukan salinan. Saran kami adalah memilih antara peminjaman, pemindahan, dan salinan berdasarkan kepemilikan yang memang diinginkan. Rust Ownership (diakses 2026/10), Variables and Data Interacting with Clone.
Apakah lifetime membuat data hidup lebih lama?
Tidak. Anotasi lifetime menyatakan hubungan masa berlaku reference dan tidak mengubah lama hidup nilainya. Contoh reference lokal yang gagal dalam paket membantu memperlihatkan batas itu. Rust Lifetimes (diakses 2026/10), Lifetime Annotation Syntax.
Apakah semua latihan bisa dijalankan tanpa internet?
Contoh dasar dan CLI tidak menggunakan dependensi pihak ketiga. Setelah toolchain terpasang, keduanya dirancang untuk build offline. API memerlukan crate luar; penggunaan offline bergantung pada ketersediaan seluruh dependensi di cache. Paket ini tidak mengemas seluruh kode dependensi atau installer Rust. Cargo Build (diakses 2026/10), offline.
Mengapa tidak langsung memakai database dan login?
Itu keputusan lingkup tutorial. Kami ingin route, respons, validasi, dan test dapat dibaca lebih dahulu. Jika aplikasi Anda membutuhkan data pribadi, rancang identitas dan izin akses sebelum memakai pola katalog publik dari contoh ini.
Apakah kode ini siap dijadikan aplikasi produksi?
Kode disiapkan untuk latihan dan pengujian lokal. API katalog memakai data statis dan belum menyediakan kebutuhan aplikasi produksi seperti pengelolaan pengguna, penyimpanan persisten, maupun konfigurasi publikasi. Gunakan sebagai titik awal belajar, kemudian tetapkan kebutuhan dan pemeriksaan untuk aplikasi nyata.
Mulai dari satu contoh, lalu jelaskan kembali
Buka kode/dasar, jalankan contoh pertama, dan ubah satu hal. Sesudah berhasil, lanjutkan sampai Anda dapat menjelaskan siapa yang memiliki data, bagaimana fungsi meminjamnya, dan bagaimana kesalahan dikembalikan. Gunakan proyek CLI untuk menyatukan konsep, kemudian proyek API untuk mengenal layanan HTTP.
Tidak perlu menambah banyak teknologi pada percobaan pertama. Pilih satu perbaikan yang dapat diuji, tulis perilaku yang diharapkan, lalu jalankan kembali pemeriksaannya. Dengan alur ini, setiap tahap menghasilkan kode yang bisa Anda pahami dan lanjutkan sendiri.
Sumber resmi dan bacaan lanjutan
Tanggal akses: 22 Oktober 2026. Bulan pada label sitasi menunjukkan waktu akses, bukan tanggal penerbitan. Contoh kode merupakan latihan asli untuk panduan ini; sumber digunakan untuk memeriksa sintaks dan perilaku bahasa.
- [Cargo Manifest, diakses 2026/10] Pengelola dokumentasi resmi. "The Manifest Format - The Cargo Book". Buka sumber.
- [Rust Ownership, diakses 2026/10] Pengelola dokumentasi resmi. "What is Ownership? - The Rust Programming Language". Buka sumber.
- [Rust Unsafe, diakses 2026/10] Pengelola dokumentasi resmi. "Unsafe Rust - The Rust Programming Language". Buka sumber.
- [Axum, diakses 2026/10] Pengelola dokumentasi resmi. "axum - Rust". Buka sumber.
- [Tokio Tutorial, diakses 2026/10] Pengelola dokumentasi resmi. "Tutorial | Tokio - An asynchronous Rust runtime". Buka sumber.
- [Cargo Book, diakses 2026/10] Pengelola dokumentasi resmi. "Hello, Cargo! - The Rust Programming Language". Buka sumber.
- [Rust Borrowing, diakses 2026/10] Pengelola dokumentasi resmi. "References and Borrowing - The Rust Programming Language". Buka sumber.
- [Rust Strings, diakses 2026/10] Pengelola dokumentasi resmi. "Storing UTF-8 Encoded Text with Strings - The Rust Programming Language". Buka sumber.
- [Rust Enum, diakses 2026/10] Pengelola dokumentasi resmi. "Defining an Enum - The Rust Programming Language". Buka sumber.
- [Rust Result, diakses 2026/10] Pengelola dokumentasi resmi. "Recoverable Errors with Result - The Rust Programming Language". Buka sumber.
- [Rust Traits, diakses 2026/10] Pengelola dokumentasi resmi. "Defining Shared Behavior with Traits - The Rust Programming Language". Buka sumber.
- [Rust Lifetimes, diakses 2026/10] Pengelola dokumentasi resmi. "Validating References with Lifetimes - The Rust Programming Language". Buka sumber.
- [Rust Getting Started, diakses 2026/10] Pengelola dokumentasi resmi. "Getting started - Rust Programming Language". Buka sumber.
- [Rustfmt, diakses 2026/10] Pengelola dokumentasi resmi. "GitHub - rust-lang/rustfmt: Format Rust code". Buka sumber.
- [Clippy, diakses 2026/10] Pengelola dokumentasi resmi. "Usage - Clippy Documentation". Buka sumber.
- [Cargo Build, diakses 2026/10] Pengelola dokumentasi resmi. "cargo build - The Cargo Book". Buka sumber.
- [Rust Functions, diakses 2026/10] Pengelola dokumentasi resmi. "Functions - The Rust Programming Language". Buka sumber.
- [Rust println, diakses 2026/10] Pengelola dokumentasi resmi. "println in std - Rust". Buka sumber.
- [Rust Variables, diakses 2026/10] Pengelola dokumentasi resmi. "Variables and Mutability - The Rust Programming Language". Buka sumber.
- [Rust Data Types, diakses 2026/10] Pengelola dokumentasi resmi. "Data Types - The Rust Programming Language". Buka sumber.
- [Rust Control Flow, diakses 2026/10] Pengelola dokumentasi resmi. "Control Flow - The Rust Programming Language". Buka sumber.
- [Rust E0382, diakses 2026/10] Pengelola dokumentasi resmi. "E0382 - Error codes index". Buka sumber.
- [Rust Slices, diakses 2026/10] Pengelola dokumentasi resmi. "The Slice Type - The Rust Programming Language". Buka sumber.
- [Rust E0499, diakses 2026/10] Pengelola dokumentasi resmi. "E0499 - Error codes index". Buka sumber.
- [Rust Methods, diakses 2026/10] Pengelola dokumentasi resmi. "Methods - The Rust Programming Language". Buka sumber.
- [Rust u64, diakses 2026/10] Pengelola dokumentasi resmi. "u64 - Rust". Buka sumber.
- [Rust Vectors, diakses 2026/10] Pengelola dokumentasi resmi. "Storing Lists of Values with Vectors - The Rust Programming Language". Buka sumber.
- [Rust HashMap, diakses 2026/10] Pengelola dokumentasi resmi. "HashMap in std::collections - Rust". Buka sumber.
- [Rust Iterators, diakses 2026/10] Pengelola dokumentasi resmi. "Processing a Series of Items with Iterators - The Rust Programming Language". Buka sumber.
- [Rust Generics, diakses 2026/10] Pengelola dokumentasi resmi. "Generic Data Types - The Rust Programming Language". Buka sumber.
- [Rust E0515, diakses 2026/10] Pengelola dokumentasi resmi. "E0515 - Error codes index". Buka sumber.
- [Rust read_to_string, diakses 2026/10] Pengelola dokumentasi resmi. "read_to_string in std::fs - Rust". Buka sumber.
- [Rust Threads, diakses 2026/10] Pengelola dokumentasi resmi. "Using Threads to Run Code Simultaneously - The Rust Programming Language". Buka sumber.
- [Rust Tests, diakses 2026/10] Pengelola dokumentasi resmi. "How to Write Tests - The Rust Programming Language". Buka sumber.
- [Rust Modules, diakses 2026/10] Pengelola dokumentasi resmi. "Control Scope and Privacy with Modules - The Rust Programming Language". Buka sumber.
- [Rust Read, diakses 2026/10] Pengelola dokumentasi resmi. "Read in std::io - Rust". Buka sumber.
- [Rust env args, diakses 2026/10] Pengelola dokumentasi resmi. "args in std::env - Rust". Buka sumber.
- [Tokio, diakses 2026/10] Pengelola dokumentasi resmi. "tokio - Rust". Buka sumber.
- [Serde Derive, diakses 2026/10] Pengelola dokumentasi resmi. "Using derive · Serde". Buka sumber.
- [Cargo Lockfile, diakses 2026/10] Pengelola dokumentasi resmi. "Cargo.toml vs Cargo.lock - The Cargo Book". Buka sumber.
- [Tower ServiceExt, diakses 2026/10] Pengelola dokumentasi resmi. "ServiceExt in tower - Rust". Buka sumber.
- [100 Proyek GitHub Pengganti Software Berbayar di Tumbas.in, diakses 2026/10] Tumbas.in. "100 Proyek GitHub Bernilai Miliaran Pengganti Software Berbayar". Buka sumber.
Komentar (0)
Belum ada komentar. Jadilah yang pertama berkomentar!
Tinggalkan Komentar