Pertama kali saya mencoba Rust, rasanya seperti bertemu dosen killer. Kode yang saya tulis dengan pede-nya ditolak kompiler terus, dengan pesan error panjang soal borrow checker yang bikin saya menggaruk kepala. Saya sempat berpikir, "bahasa apa ini, kok nyusahin banget?" Tapi setelah saya memaksa diri menyelesaikan satu project kecil, semuanya berubah. Sekarang Rust jadi bahasa favorit saya buat tooling dan aplikasi yang butuh performa tinggi.
Kalau kamu developer yang sudah terbiasa dengan JavaScript, Python, atau PHP, artikel ini buat kamu. Saya akan ajak kamu belajar Rust dari nol dengan cara paling praktis: membangun CLI tool sungguhan pakai Cargo. Bukan teori belaka, tapi kode yang bisa langsung kamu jalankan.
Kenapa Rust Layak Kamu Pelajari di 2026
Rust itu bahasa pemrograman sistem yang dikembangkan Mozilla, sekarang dikelola oleh Rust Foundation. Keunggulan utamanya: memory safety tanpa garbage collector. Artinya program Rust tidak akan kena segfault, use-after-free, atau data race - dan semuanya dicek di waktu kompilasi, bukan runtime. Ini kombinasi yang jarang ada: secepat C/C++, tapi seaman bahasa modern.
Bukan cuma teori. Perusahaan besar sudah memakai Rust di production:
- Firefox memakai Rust untuk engine CSS-nya (Servo/Quantum).
- Cloudflare memakai Rust untuk pingora, pengganti nginx mereka.
- Discord memakai Rust untuk layanan real-time yang butuh latensi rendah.
- Dropbox memakai Rust untuk sistem sync file-nya.
Bahkan tool yang sering kamu pakai sehari-hari seperti ripgrep, bat, fd, dan uv (Python package manager baru) semuanya ditulis dengan Rust. Di Indonesia sendiri, demand developer Rust mulai naik, terutama untuk backend, blockchain, dan embedded. Jadi investasi waktu belajar Rust sekarang itu keputusan yang masuk akal.
Install Rust dengan rustup
Cara paling resmi dan gampang install Rust adalah pakai rustup, toolchain manager resmi. Di Linux atau macOS, buka terminal lalu jalankan:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Di Windows, download installer dari rustup.rs dan jalankan seperti biasa. Setelah selesai, source environment-nya biar perintah cargo kebaca:
source "$HOME/.cargo/env"
Cek instalasi dengan perintah berikut:
rustc --version
cargo --version
Kalau muncul versi seperti rustc 1.85.0, berarti Rust sudah siap. Satu hal yang saya suka dari rustup: update Rust semudah rustup update, dan kamu bisa punya beberapa versi toolchain sekaligus untuk project berbeda.
Project Pertama: cargo new
Cargo itu package manager sekaligus build system bawaan Rust. Dia berperan seperti npm + webpack, atau composer + artisan. Untuk bikin project baru:
cargo new cekfile
cd cekfile
Struktur folder yang dihasilkan sangat sederhana:
cekfile/
|-- Cargo.toml # config project dan dependencies
|-- src/
| `-- main.rs # kode utama
`-- .gitignore
Coba jalankan program default-nya:
cargo run
Kamu akan lihat output Hello, world!. Bedanya dengan bahasa lain, cargo run ini otomatis compile dulu baru eksekusi. Kalau ada error, kompiler langsung kasih tahu di mana dan kenapa.
Membangun CLI Tool: cekfile
Sekarang bagian serunya. Kita bikin tool bernama cekfile yang menerima nama file dari argumen, lalu menampilkan ukuran file, jumlah baris, dan tipe filenya. Buka src/main.rs dan ganti isinya dengan kode ini:
use std::env;
use std::fs;
struct FileInfo {
name: String,
size_bytes: u64,
line_count: usize,
}
impl FileInfo {
fn from_path(path: &str) -> Result<FileInfo, String> {
let meta = fs::metadata(path).map_err(|e| format!("Gagal baca file: {}", e))?;
if !meta.is_file() {
return Err(format!("{} bukan file biasa", path));
}
let content = fs::read_to_string(path)
.map_err(|e| format!("Gagal membaca isi file: {}", e))?;
let line_count = content.lines().count();
Ok(FileInfo {
name: path.to_string(),
size_bytes: meta.len(),
line_count,
})
}
fn human_size(&self) -> String {
let kb = self.size_bytes as f64 / 1024.0;
let mb = kb / 1024.0;
if mb >= 1.0 {
format!("{:.2} MB", mb)
} else if kb >= 1.0 {
format!("{:.2} KB", kb)
} else {
format!("{} bytes", self.size_bytes)
}
}
}
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Cara pakai: cekfile <nama_file>");
std::process::exit(1);
}
let path = &args[1];
match FileInfo::from_path(path) {
Ok(info) => {
println!("Nama file : {}", info.name);
println!("Ukuran : {}", info.human_size());
println!("Jumlah baris: {}", info.line_count);
}
Err(err) => {
eprintln!("Error: {}", err);
std::process::exit(1);
}
}
}
Jalankan dengan:
cargo run -- Cargo.toml
Outputnya kira-kira begini:
Nama file : Cargo.toml
Ukuran : 232 bytes
Jumlah baris: 9
Selamat, kamu baru saja membangun CLI tool pertama dengan Rust. Kode ini walau sederhana, sudah memakai beberapa konsep inti Rust: struct, impl, Result untuk error handling, pattern matching dengan match, dan ownership lewat parameter &str.
Ownership dan Borrowing: Konsep yang Bikin Nyerah
Kalau kamu baru dari Python atau JavaScript, konsep ownership ini yang paling bikin pusing. Intinya: setiap nilai di Rust punya satu pemilik. Saat pemiliknya keluar dari scope, nilainya otomatis dibersihkan. Tidak ada garbage collector yang jalan di background.
let s1 = String::from("halo");
let s2 = s1; // s1 dipindah (moved) ke s2
// println!("{}", s1); // ERROR: s1 sudah tidak valid
println!("{}", s2); // OK
Kalau kamu cuma mau pinjam nilainya tanpa memindahkan, pakai reference dengan &:
fn hitung_panjang(s: &String) -> usize {
s.len()
}
let nama = String::from("rust");
let panjang = hitung_panjang(&nama); // nama tetap bisa dipakai
println!("{} punya {} huruf", nama, panjang);
Aturannya cuma dua: boleh punya banyak reference read-only (&T), tapi cuma boleh satu reference mutable (&mut T) dalam satu waktu. Kompiler memastikan ini di compile time, jadi data race mustahil terjadi. Awalnya terasa menyebalkan, tapi justru ini yang bikin program Rust dijamin aman. Setelah dua minggu, otak kamu akan otomatis berpikir dalam ownership, dan error borrow checker jadi jarang muncul.
Satu konsep kecil yang sering bikin bingung di awal: beda String dan &str. String itu data yang dimiliki dan bisa diubah-ubah, sedangkan &str itu sekadar "pinjaman" berupa slice teks. Analoginya: String seperti punya mobil sendiri, &str seperti numpang lihat garasinya. Di kode cekfile tadi, fungsi from_path menerima &str karena dia cuma perlu membaca path-nya, tidak perlu menyimpannya. Pola ini bikin fungsi lebih fleksibel dan tidak memaksa pemanggil menyerahkan kepemilikan datanya.
Ekosistem Cargo: crates.io dan Library Favorit
Salah satu kekuatan Rust ada di ekosistem crate-nya. Crate itu istilah Rust untuk package/library. Registry resminya di crates.io, dan menambahkan dependency semudah mengedit Cargo.toml:
[dependencies]
clap = { version = "4", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
Lalu jalankan cargo build, dan Cargo otomatis download serta compile dependency-nya. Beberapa crate yang paling sering saya pakai:
- clap - parsing argumen CLI yang powerful. Kalau tool kamu makin kompleks, ganti
env::argsmanual dengan clap biar dapat subcommand, flag, dan help text gratis. - serde - serialisasi/deserialisasi JSON, YAML, dan format lain. Wajib buat API atau config file.
- rayon - parallel processing semudah mengubah
iter()jadipar_iter(). - tokio - async runtime untuk aplikasi network dan backend.
- anyhow - error handling yang ergonomis untuk aplikasi, bukan library.
Menariknya, karena semua dependency di-compile bareng dengan kode kamu, binary hasil build itu self-contained. Tidak perlu install runtime di server target seperti Node.js atau Python.
Build Release dan Deploy ke VPS
Setelah tool kamu beres, build versi release yang dioptimalkan:
cargo build --release
Binary-nya ada di target/release/cekfile. Karena Rust compile statis (defaultnya), kamu bisa copy binary ini ke VPS mana pun dengan arsitektur yang sama, dan langsung jalan tanpa install apa pun:
scp target/release/cekfile user@vps:/usr/local/bin/
ssh user@vps
cekfile /var/log/nginx/access.log
Ini salah satu alasan kenapa tool-tool CLI populer seperti ripgrep dan bat gampang didistribusikan: cukup satu file binary, tidak ada dependency hell. Untuk ukuran, binary release Rust yang sederhana biasanya 300 KB sampai 3 MB, jauh lebih kecil daripada bundle Node.js.
Troubleshooting Umum untuk Pemula
Selama belajar, kamu hampir pasti nemu error-error ini. Ini cara cepat mengatasinya:
- "borrow of moved value" - kamu memakai variabel setelah dipindah. Solusinya: clone nilainya (
.clone()) kalau memang perlu salinan, atau pakai reference&. - "cannot borrow as mutable" - ada dua reference mutable ke data yang sama. Solusinya: scope-kan pemakaiannya atau pakai struktur seperti
RefCellkalau benar-benar butuh. - "expected &str, found String" - masalah tipe reference. Tambahkan
&di depan nilai, atau pakai.as_str(). cargo: command not found- environment belum di-source. Jalankansource "$HOME/.cargo/env"atau tambahkan ke.bashrc.- Compile lama - wajar untuk first build karena semua dependency di-compile. Build berikutnya cepat karena pakai cache incremental.
Pesan error Rust terkenal detail dan helpful. Kompiler sering kasih saran perbaikan lengkap dengan contoh kode. Biasakan baca error dari atas ke bawah, jangan langsung panik lihat panjangnya.
Menulis Unit Test dengan cargo test
Testing di Rust itu first-class, bukan fitur tambahan. Kamu cukup menulis fungsi test dengan atribut #[test] di file yang sama, lalu jalankan cargo test. Tidak perlu setup framework tambahan seperti Jest atau PHPUnit. Contohnya, tambahkan kode ini di bawah fungsi main di main.rs:
#[cfg(test)]
mod tests {
use super::FileInfo;
#[test]
fn human_size_menampilkan_kb() {
let info = FileInfo {
name: "file.txt".to_string(),
size_bytes: 2048,
line_count: 10,
};
assert_eq!(info.human_size(), "2.00 KB");
}
#[test]
fn from_path_error_untuk_file_tidak_ada() {
let result = FileInfo::from_path("/tmp/tidak-ada-file-xyz.txt");
assert!(result.is_err());
}
}
Jalankan dengan:
cargo test
Outputnya akan menunjukkan dua test yang lewat. Konsep #[cfg(test)] artinya modul ini hanya di-compile saat testing, jadi tidak menambah ukuran binary production. Kebiasaan yang saya sarankan: tulis test untuk fungsi logika seperti human_size sebelum menambah fitur baru. Ini mencegah regresi diam-diam saat tool kamu makin besar.
Rust vs Go vs C: Kapan Memakai yang Mana
Pertanyaan yang sering muncul: kenapa tidak pakai Go atau C saja? Semua punya posisinya masing-masing, dan pemahaman ini membantu kamu memilih tool yang tepat di project nyata:
- C - paling dekat dengan hardware, kontrol penuh, tapi tanggung jawab memory management ada di kamu sepenuhnya. Cocok untuk kernel, driver, dan embedded yang sangat terbatas. Risiko: bug memory yang susah dilacak.
- Go - syntax sederhana, garbage collector, compile cepat, cocok untuk backend API dan microservice. Tim yang butuh on-boarding cepat biasanya pilih Go. Trade-off: kontrol memory lebih kasar dan performa di bawah Rust untuk workload berat.
- Rust - keamanan memory di compile time, performa setara C, dan ekosistem tooling yang modern. Cocok untuk CLI tool, sistem yang butuh keandalan tinggi, WebAssembly, dan backend berperforma ekstrem. Trade-off: kurva belajar paling curam.
Kalau project kamu backend CRUD biasa, Go atau bahkan PHP/Laravel tetap pilihan yang masuk akal. Tapi kalau kamu butuh tool kecil yang cepat, aman, dan gampang didistribusikan - seperti yang kita buat hari ini - Rust unggul jauh. Binary-nya kecil, jalan tanpa runtime, dan tidak mungkin kena memory leak.
Langkah Selanjutnya
Kalau artikel ini sudah kamu praktikkan, coba tantangan berikut untuk naik level:
- Ganti parsing argumen manual dengan crate clap, tambahkan subcommand dan flag
--jsonuntuk output JSON. - Pakai serde_json untuk membaca file config dan menampilkan datanya.
- Buat tool yang membaca folder berisi banyak file dan menampilkan total ukurannya - ini latihan bagus untuk
std::fsdan rekursi. - Coba tulis unit test dengan
#[cfg(test)]dan jalankan pakaicargo test. Testing di Rust itu first-class, dancargo testlangsung terintegrasi. - Kalau sudah pede, baca buku resmi The Rust Programming Language di doc.rust-lang.org - gratis dan salah satu dokumentasi terbaik di dunia programming.
Kesimpulan
Rust memang punya kurva belajar yang curam di awal, terutama karena konsep ownership yang tidak ada di bahasa lain. Tapi justru di situlah nilainya: setelah kamu menguasainya, kamu bisa menulis program yang cepat, aman, dan bisa di-deploy sebagai satu binary tanpa runtime. CLI tool sederhana yang kita buat hari ini sudah menyentuh fondasi paling penting: struct, error handling, ownership, dan ekosistem Cargo.
Menurut kamu, bagian mana yang paling susah saat pertama kali belajar Rust - borrow checker, atau setup toolchain? Cerita di kolom komentar ya, dan kalau ada error yang membuatmu buntu, tulis saja di sana. Siapa tahu pengalamanmu membantu developer lain yang sedang di fase yang sama.