Halo teman-teman semuanya, pada artikel sebelumnya kita sudah membahas tentang ownership, yaitu aturan kepemilikan nilai di Rust.
Kita belajar bahwa setiap nilai hanya bisa dimiliki oleh satu variabel pada satu waktu, dan ketika ownership berpindah maka pemilik sebelumnya tidak bisa lagi mengakses nilai tersebut.
Aturan ini membuat Rust sangat aman dalam pengelolaan memori, tetapi terkadang terasa merepotkan ketika kita hanya ingin menggunakan nilai tanpa benar-benar mengambil kepemilikannya.
Untuk mengatasi hal itu, Rust menyediakan konsep borrowing dan references. Dengan borrowing, kita bisa “meminjam” sebuah nilai tanpa harus memindahkan ownership.
Konsep ini sangat penting, karena hampir semua kode Rust nyata menggunakan borrowing agar fleksibel sekaligus aman.
Apa Itu Reference?
Reference adalah sebuah pointer yang menunjuk ke sebuah nilai tanpa mengambil ownership-nya. Reference ditulis dengan simbol &
.
fn main() {
let s1 = String::from("hello");
cetak(&s1); // kita meminjam s1
println!("Masih bisa pakai s1: {}", s1);
}
fn cetak(s: &String) {
println!("Isi: {}", s);
}
Pada contoh di atas, kita mengirim &s1
ke fungsi cetak
. Artinya, fungsi cetak
hanya meminjam s1
tanpa mengambil ownership. Setelah fungsi selesai, s1
masih bisa digunakan di main
.
Mutable Reference
Secara default, reference di Rust bersifat immutable (tidak bisa mengubah nilai). Jika kita ingin meminjam data sekaligus mengubahnya, kita bisa menggunakan mutable reference dengan &mut
.
fn main() {
let mut s = String::from("hello");
ubah(&mut s);
println!("Setelah diubah: {}", s);
}
fn ubah(str: &mut String) {
str.push_str(" world");
}
Fungsi ubah
menerima &mut String
, sehingga bisa menambahkan kata " world"
ke dalam string yang dipinjam.
Aturan Borrowing
Rust memiliki aturan ketat untuk mencegah error yang berhubungan dengan data race. Aturan tersebut adalah:
- Kita hanya boleh memiliki satu mutable reference pada suatu waktu.
- Kita boleh memiliki beberapa immutable reference, tetapi tidak boleh bersamaan dengan mutable reference.
fn main() {
let mut s = String::from("data");
let r1 = &s;
let r2 = &s;
// let r3 = &mut s; // error: tidak boleh ada mutable ref jika masih ada immutable ref
println!("{}, {}", r1, r2);
}
Aturan ini mencegah konflik antara pembacaan data dan penulisan data yang bisa menyebabkan perilaku tidak terduga.
Dangling References
Rust juga melarang reference menggantung (dangling reference), yaitu reference yang menunjuk ke data yang sudah dibebaskan.
fn buat_ref() -> &String {
let s = String::from("halo");
&s // error: s akan di-drop setelah fungsi selesai
}
Kode di atas tidak akan bisa di-compile. Rust akan menghentikan kita sebelum program berjalan agar tidak ada reference ke data yang sudah tidak valid.
Kesimpulan
Pada artikel ini kita telah mempelajari tentang borrowing dan references di Rust. Kita bisa meminjam data dengan &
untuk immutable reference, atau &mut
untuk mutable reference.
Kita juga melihat aturan borrowing yang ketat, yaitu hanya satu mutable reference pada satu waktu, atau beberapa immutable reference tanpa mutable reference. Rust bahkan melindungi kita dari dangling reference dengan melakukan pemeriksaan saat compile.
Konsep borrowing ini sangat penting, karena dengan inilah Rust bisa memastikan keamanan memori sekaligus fleksibilitas dalam mengelola data.
Pada artikel berikutnya, kita akan membahas tentang Slice & String di Rust, yang sering digunakan dalam manipulasi data teks maupun koleksi.
Terima Kasih