Menulis semua kebutuhan program dari nol adalah pilihan yang mahal: pengacakan angka butuh algoritma teruji, format tanggal butuh penanganan kalender, dan serialisasi data butuh ratusan detail. Ekosistem Rust menjawabnya dengan crates.io — registry publik yang menampung puluhan ribu crate siap pakai yang dipublikasikan komunitas. Cargo terintegrasi penuh dengan registry tersebut: satu perintah cargo add cukup untuk mengunduh, mengompilasi, dan menautkan library eksternal ke proyek kita. Pada Chapter ini kita menambahkan crate rand ke proyek undian, mengamati seluruh proses di balik layar mulai dari unduhan sampai terbentuknya berkas kunci versi, lalu memakai library tersebut dalam kode sungguhan.
Registry crates.io dan Peran Cargo #
crates.io berperan sebagai registry: server tempat crate dipublikasikan, dicari, dan diunduh. Setiap crate di registry punya nama unik, nomor versi, dan daftar versi rilisnya. Registry juga menyimpan index — kumpulan metadata ringkas berisi nama, versi, dan dependency tiap crate — yang bisa diperiksa cargo dengan cepat tanpa mengunduh isi crate sepenuhnya.
Cargo memakai registry ini lewat dua jalur: jalur metadata saat menyelesaikan versi mana yang dipasang, dan jalur unduhan saat mengambil berkas sumber crate. Kedua jalur tersebut otomatis dijalankan oleh cargo build — kita tidak pernah mengunduh dan mengekstrak berkas secara manual seperti pada beberapa bahasa lain. Semua berkas yang pernah diunduh tersimpan di cache ~/.cargo/registry, sehingga proyek lain yang memakai crate sama tidak mengunduh ulang.
Cache tersebut terbagi dua subfolder dengan tugas berbeda: ~/.cargo/registry/cache menampung arsip .crate terkompresi persis seperti yang diunggah penulisnya, sedangkan ~/.cargo/registry/src menampung hasil ekstraksinya yang dipakai rustc saat kompilasi. Pemisahan ini menjelaskan mengapa menghapus satu subfolder tidak merusak yang lain — cargo cukup mengekstrak ulang dari arsip tanpa menyentuh jaringan.
Menambahkan Dependency dengan cargo add #
Proyek kita bernama undian-acak: sebuah program yang memilih satu pemenang dari daftar peserta. Kebutuhan pengacakan tidak perlu kita tulis sendiri — crate rand adalah standar de facto di ekosistem Rust. Masuk ke folder proyek, lalu jalankan:
cargo add randOutput yang Dihasilkan:
Updating crates.io index
Adding rand v0.10.3 to dependencies
Features:
+ alloc
+ std
+ std_rng
+ sys_rng
+ thread_rng
- chacha
- log
- serde
- simd_support
- unbiased
Updating crates.io index
Locking 8 packages to highest Rust 1.99.0 compatible versionsPerintah sekecil itu melakukan tiga hal. Pertama, cargo menyegarkan salinan index crates.io — baris Updating crates.io index. Kedua, cargo menuliskan baris rand = "0.10.3" ke tabel [dependencies] di Cargo.toml, dengan versi terbaru yang ditemukannya. Ketiga, cargo menyelesaikan dependency dan menampilkan daftar features milik rand — tanda + berarti aktif secara bawaan, tanda - berarti nonaktif; daftar ini pemanasan untuk Chapter Fitur Features. Baris Locking 8 packages memberi tahu bahwa rand membawa serta tujuh crate pendukung, dan seluruh rangkaian itu dicatat versi pastinya ke Cargo.lock.
Manifest proyek kini memuat satu baris dependency:
[package]
name = "undian-acak"
version = "0.1.0"
edition = "2024"
[dependencies]
rand = "0.10.3"Apa yang Terjadi Saat cargo build Pertama #
Dengan dependency tercatat di manifest, cargo build menjalankan rangkaian proses yang lebih panjang dari biasanya:
cargo buildOutput yang Dihasilkan:
Downloading crates ...
Downloaded cfg-if v1.0.5
Downloaded rand_core v0.10.1
Downloaded cpufeatures v0.3.1
Downloaded getrandom v0.4.3
Downloaded chacha20 v0.10.2
Downloaded rand v0.10.3
Downloaded libc v0.2.190
Compiling libc v0.2.190
Compiling cfg-if v1.0.5
Compiling getrandom v0.4.3
Compiling rand_core v0.10.1
Compiling cpufeatures v0.3.1
Compiling chacha20 v0.10.2
Compiling rand v0.10.3
Compiling undian-acak v0.1.0 (/tmp/w5a/undian-acak)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.94sAlur di balik layar berjalan berurutan. Cargo membaca tabel [dependencies], memeriksa Cargo.lock — berkas baru yang barusan dibuat — untuk mengetahui versi pasti tiap crate, mengunduh berkas sumber ke cache ~/.cargo/registry, lalu mengompilasi dependency satu per satu mulai dari yang paling dasar: libc dan cfg-if dikerjakan lebih dulu karena tidak bergantung pada apa pun, rand_core menyusul, hingga akhirnya rand sendiri, baru kemudian kode kita. Cargo juga menjalankan kompilasi dependency yang saling bebas secara paralel — jumlah proses rustc yang hidup bersamaan mengikuti banyaknya inti prosesor — sehingga proyek dengan puluhan dependency tetap selesai dalam waktu wajar. Unduhan hanya terjadi sekali — cargo build kedua tanpa perubahan hanya melaporkan Finished ... in 0.01s karena semua crate di cache dan hasil kompilasi masih valid.
Berkas Cargo.lock yang tercipta merekam resolusi versi:
[[package]]
name = "rand"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"Setiap entri menyimpan versi pasti, sumber registry, dan checksum untuk memastikan berkas yang diunduh tidak berubah. Nilai rand = "0.10.3" di manifest sebenarnya adalah requirement — rentang versi yang diterima — sedangkan Cargo.lock yang menyimpan versi final yang terpasang. Perbedaan keduanya menjadi pokok bahasan Chapter Versi dan SemVer.
Perilaku berkas lock paling terasa pada kondisi nyata: rekan tim yang meng-clone repositori kita mendapatkan Cargo.lock yang sama, sehingga cargo build di komputernya memakai rand 0.10.3 dan keenam pendukungnya dengan versi identik tanpa satu pun keputusan ulang. Registry tetap disentuh hanya untuk mengunduh berkas yang belum ada di cache — versi sudah diputuskan sejak awal.
Menggunakan rand dalam Program #
Kode sumber src/main.rs memakai rand untuk memilih pemenang:
use rand::{rng, RngExt};
fn main() {
let peserta = ["Budi", "Siti", "Rina", "Agus", "Dewi"];
let indeks = rng().random_range(0..peserta.len());
let pemenang = peserta[indeks];
println!("Pemenang undian bulan ini: {}", pemenang);
println!("Kupon keberuntungan: {}", rng().random_range(1000..9999));
}Jalankan program beberapa kali:
cargo run
cargo run
cargo runOutput yang Dihasilkan:
Pemenang undian bulan ini: Rina
Kupon keberuntungan: 4313Pemenang undian bulan ini: Dewi
Kupon keberuntungan: 9343Pemenang undian bulan ini: Budi
Kupon keberuntungan: 1050Mari kita bedah kode di atas:
- Baris 1 (
use rand::{rng, RngExt};): mengimpor dua item dari crate rand — fungsirngyang membuat generator angka acak dari sumber sistem operasi, dan traitRngExtpemilik metoderandom_range. Trait harus dibawa ke scope agar metodenya bisa dipanggil, sesuai aturan yang sudah kita kenal di Section Traits. - Baris 4 (
let peserta = ["Budi", "Siti", "Rina", "Agus", "Dewi"];): array lima peserta sebagai data undian. - Baris 5 (
let indeks = rng().random_range(0..peserta.len());):rng()membuat generator, lalurandom_rangemengambil satu angka dari rentang0..5. Rentang eksklusif ujung membuat hasil maksimal4— selalu menjadi indeks sah array. - Baris 6 (
let pemenang = peserta[indeks];): mengambil nama pemenang dari array lewat indeks acak tersebut. - Baris 8 (
println!("Kupon keberuntungan: {}", rng().random_range(1000..9999));): generator kedua mengambil nomor kupon empat digit; rentang1000..9999tidak pernah menghasilkan angka di bawah seribu.
Tiga kali menjalankan menghasilkan tiga hasil berbeda — perilaku persis yang kita cari dari library pengacakan.
Menghapus Dependency #
Kebalikan cargo add tersedia untuk membersihkan manifest — misalnya ketika library ternyata tidak terpakai:
cargo remove randOutput yang Dihasilkan:
Removing rand from dependenciesPerintah tersebut menghapus baris rand = "0.10.3" dari tabel [dependencies]; kode yang masih mengimpor rand akan gagal dikompilasi dengan E0432 sampai baris use ikut dibersihkan. Crate yang terlanjur terunduh tetap tinggal di cache ~/.cargo/registry — cache bersifat arsip, bukan daftar aktif proyek, sehingga tidak memengaruhi build mana pun.
Ringkasan #
cargo add rand menuliskan requirement versi ke manifest, mengunduh crate beserta dependency pendukungnya dari crates.io ke cache lokal, mengompilasi berurutan dari paling dasar, dan merekam hasil resolusi ke Cargo.lock. Kode kita tinggal mengimpor item publik crate lewat use — fungsi rng dan metode random_range milik trait RngExt menghasilkan angka acak yang berubah di tiap eksekusi. Requirement "0.10.3" yang ditulis cargo add bukan versi terpasang yang kaku, melainkan rentang; cara membaca rentang itulah pembahasan Chapter berikutnya.