Halo teman-teman semuanya, pada artikel sebelumnya kita sudah membahas tentang trait di Rust. Kita melihat bagaimana trait memungkinkan kita mendefinisikan perilaku yang bisa dibagi ke berbagai tipe, menyediakan default implementation, digunakan sebagai trait bound untuk generics, bahkan sampai bisa dipakai untuk operator overloading.
Sekarang kita akan berpindah ke topik yang tidak kalah penting yaitu module & package di Rust. Jika program kita semakin besar, maka akan semakin sulit mengatur semua kode dalam satu file.
Oleh karena itu, Rust menyediakan sistem modular yang rapi dan terstruktur untuk mengelola kode. Ada beberapa istilah penting yang perlu kita pahami:
- Module (
mod
): cara untuk mengelompokkan kode di dalam satu crate. Module membantu kita memisahkan fungsi, struct, enum, dan konstanta ke dalam unit yang lebih kecil.
- Package: sekumpulan crate yang dikelola bersama-sama.
- Crate: unit terkecil dalam ekosistem Rust. Satu crate bisa berupa binary (aplikasi yang bisa dijalankan) atau library (kumpulan kode yang bisa digunakan oleh crate lain).
- Cargo: tool bawaan Rust untuk manajemen project, dependency, build, dan distribusi.
Dengan memahami module dan package, kita bisa menulis kode Rust yang lebih terstruktur, mudah dikelola, dan siap untuk skala besar.
Membuat Module dengan mod
Kita bisa membuat module langsung di dalam file dengan keyword mod
.
mod math {
pub fn tambah(a: i32, b: i32) -> i32 {
a + b
}
pub fn kali(a: i32, b: i32) -> i32 {
a * b
}
}
fn main() {
let hasil = math::tambah(3, 4);
println!("Hasil tambah: {}", hasil);
}
Di sini kita membuat module math
yang berisi dua fungsi. Keyword pub
digunakan agar fungsi bisa diakses dari luar module.
Memisahkan Module ke File Terpisah
Agar kode lebih rapi, module bisa dipisahkan ke file lain. Misalnya kita punya struktur project:
src
├── main.rs
└── math.rs
Isi file main.rs
:
mod math;
fn main() {
let hasil = math::kali(5, 6);
println!("Hasil kali: {}", hasil);
}
Isi file math.rs
:
pub fn tambah(a: i32, b: i32) -> i32 {
a + b
}
pub fn kali(a: i32, b: i32) -> i32 {
a * b
}
Dengan cara ini, module math
dipisahkan ke file tersendiri tetapi tetap bisa digunakan di main.rs
.
Sub-Module
Module juga bisa memiliki sub-module. Struktur project:
src
├── main.rs
└── utils
├── mod.rs
└── string_utils.rs
Isi file main.rs
:
mod utils;
fn main() {
utils::string_utils::cetak("Halo Rust!");
}
Isi file utils/mod.rs
:
pub mod string_utils;
Isi file utils/string_utils.rs
:
pub fn cetak(text: &str) {
println!("{}", text);
}
Di sini kita membuat folder utils
sebagai module dengan file mod.rs
, lalu menambahkan sub-module string_utils
.
Crate dan Package
- Crate: satuan kode Rust yang di-compile menjadi library atau binary.
- Package: sekumpulan crate yang dikelola dengan satu
Cargo.toml
.
Contoh: jika kita membuat project baru dengan cargo new hello
, maka kita membuat package dengan satu crate binary di dalamnya (src/main.rs
).
Jika kita ingin membuat library, gunakan:
cargo new mylib --lib
Maka Rust akan membuat crate library dengan src/lib.rs
.
Menggunakan Crate Eksternal
Rust memiliki ekosistem crate yang sangat luas melalui crates.io. Untuk menggunakan crate eksternal, kita cukup menambahkannya di Cargo.toml
.
Contoh menggunakan crate rand
:
Cargo.toml
[dependencies]
rand = "0.8"
main.rs
use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let n: i32 = rng.gen_range(1..=10);
println!("Angka acak: {}", n);
}
Cargo akan otomatis mengunduh dan mengelola dependency tersebut.
Kesimpulan
Pada artikel ini kita sudah belajar tentang module & package di Rust. Kita memahami bagaimana membuat module dengan mod
, memisahkan module ke file, membuat sub-module, serta mengenal crate dan package. Kita juga melihat bagaimana menggunakan crate eksternal dari crates.io melalui Cargo.
Dengan sistem module dan package, Rust memberikan cara yang rapi dan terorganisir untuk mengelola kode, baik dalam project kecil maupun besar.
Pada artikel berikutnya, kita akan membahas tentang Error Handling di Rust, termasuk panic!
, unwrap
, expect
, dan operator ?
.
Terima Kasih