19 Nisan 2025
Rust, Stack Overflow anketlerinde üst üste yıllarca “en sevilen” programlama dili unvanını alarak geliştiricilerin ilgisini sürekli olarak çekmektedir. Bu sadece bir abartı değil; Rust, diğer sistem programlama dillerinde bulunan yaygın zorlukları ele alan performans, güvenlik ve modern dil özelliklerinin etkileyici bir karışımını sunar. Rust'ı özel kılan şeyin ne olduğunu merak ediyorsanız ve yolculuğunuza başlamak istiyorsanız, bu başlangıç kılavuzu size başlamak için temel bilgileri sağlar. Temel sözdizimini, sahiplik gibi benzersiz kavramları ve Rust ekosistemini güçlendiren temel araçları keşfedeceğiz.
Rust, kendini güvenilir ve verimli yazılımlar oluşturmaya yönelik bir dil olarak konumlandırır. Başlıca avantajları, bir çöp toplayıcıya güvenmeden bellek güvenliği sağlaması ve korkusuz eşzamanlılığa olanak tanıması etrafında döner. İşte Rust öğrenmeyi düşünmeniz için nedenler:
İlk Rust kod satırınızı yazmadan önce, Rust araç zincirini kurmanız gerekir. Rust'ı kurmanın standart ve önerilen yolu, Rust araç zinciri yükleyicisi olan rustup
kullanmaktır.
rustup
: Bu komut satırı aracı, Rust kurulumlarınızı yönetir. Farklı Rust sürümlerini (kararlı, beta veya nightly sürümleri gibi) kurmanıza, güncellemenize ve bunlar arasında kolayca geçiş yapmanıza olanak tanır. İşletim sisteminize özel kurulum talimatları için resmi Rust web sitesini (https://www.rust-lang.org/tools/install) ziyaret edin.rustc
: Bu, Rust derleyicisidir. Rust kaynak kodunuzu .rs
dosyalarına yazdıktan sonra, rustc
bunları bilgisayarınızın anlayabileceği çalıştırılabilir ikili dosyalara veya kütüphanelere derler. Kritik olmasına rağmen, günlük iş akışınızda rustc
'yi doğrudan çok sık çağırmazsınız.cargo
: Bu, Rust'ın derleme sistemi ve paket yöneticisidir ve en sık etkileşimde bulunacağınız araçtır. Cargo, birçok yaygın geliştirme görevini düzenler:
cargo new
).cargo build
).cargo run
).cargo test
).Cargo.toml
dosyanızda listelenen harici kütüphaneleri veya crate'leri otomatik olarak alma ve derleme).Yerel bir kuruluma ihtiyaç duymadan hızlı denemeler yapmak için, resmi Rust Playground gibi çevrimiçi platformlar veya Replit gibi entegre geliştirme ortamları mükemmel seçeneklerdir.
Herhangi bir yeni dili öğrenmek için bir geçiş töreni olan geleneksel “Merhaba, dünya!” programıyla başlayalım. main.rs
adında bir dosya oluşturun ve aşağıdaki kodu ekleyin:
fn main() {
// Bu satır konsola metin yazdırır
println!("Merhaba Rust!");
}
Bu basit programı temel araçları kullanarak derlemek ve çalıştırmak için:
main.rs
dosyasını içeren dizine gidin ve şunu çalıştırın:
rustc main.rs
Bu komut, çalıştırılabilir bir dosya (örneğin, Linux/macOS'ta main
, Windows'ta main.exe
) oluşturan Rust derleyicisini (rustc
) çağırır../main
# Windows'ta şunu kullanın: .\main.exe
Ancak, tek bir dosyanın ötesindeki her şey için Cargo kullanmak standart ve çok daha kullanışlı bir yaklaşımdır:
cargo new merhaba_rust
cd merhaba_rust
Cargo, merhaba_rust
adında yeni bir dizin oluşturur; bu dizin, içinde main.rs
bulunan (zaten “Merhaba Rust!” koduyla doldurulmuş) bir src
alt dizinini ve Cargo.toml
adında bir yapılandırma dosyasını içerir.cargo run
Cargo, derleme adımını halledecek ve ardından ortaya çıkan programı çalıştırarak konsolunuzda “Merhaba Rust!” görüntüleyecektir.Kod parçacığını inceleyelim:
fn main()
: Bu, ana fonksiyonu tanımlar. fn
anahtar kelimesi bir fonksiyon bildirimini belirtir. main
özel bir fonksiyon adıdır; her çalıştırılabilir Rust programının çalışmaya başladığı giriş noktasıdır. Parantezler ()
, bu fonksiyonun girdi parametresi almadığını gösterir.{}
: Süslü parantezler bir kod bloğunu veya kapsamı tanımlar. Fonksiyona ait tüm kod bu parantezlerin içine girer.println!("Merhaba Rust!");
: Bu satır, konsola metin yazdırma eylemini gerçekleştirir.
println!
bir Rust makrosudur. Makrolar fonksiyonlara benzer ancak önemli bir farkları vardır: ünlem işareti !
ile biterler. Makrolar derleme zamanı kod üretimi gerçekleştirerek normal fonksiyonlardan daha fazla güç ve esneklik sunar (println!
'in yaptığı gibi değişken sayıda argümanı işlemek gibi). println!
makrosu sağlanan metni konsola yazdırır ve sonuna otomatik olarak bir yeni satır karakteri ekler."Merhaba Rust!"
bir dizi (string) sabitidir – çift tırnak içine alınmış, metni temsil eden sabit bir karakter dizisidir.;
: Noktalı virgül, ifadenin sonunu işaretler. Çalıştırılabilir Rust kodunun çoğu satırı (ifadeler) noktalı virgülle biter.Şimdi, Rust programlama dilinin temel yapı taşlarına dalalım.
Değişkenler, veri değerlerini saklamak için kullanılır. Rust'ta değişkenleri let
anahtar kelimesiyle bildirirsiniz.
let elmalar = 5;
let mesaj = "Beş tane al";
Rust'ta temel bir kavram, değişkenlerin varsayılan olarak değişmez olmasıdır. Bu, bir değer bir değişken adına bağlandıktan sonra, o değeri daha sonra değiştiremeyeceğiniz anlamına gelir.
let x = 10;
// x = 15; // Bu satır derleme zamanı hatasına neden olur! Değişmez `x` değişkenine iki kez atama yapılamaz.
println!("x'in değeri: {}", x); // {} x'in değeri için bir yer tutucudur
Bu varsayılan değişmezlik, yaygın bir hata kaynağı olabilen verilerin kazara değiştirilmesini önleyerek daha güvenli, daha öngörülebilir kod yazmanıza yardımcı olan kasıtlı bir tasarım seçimidir. Değeri değişebilen bir değişkene ihtiyacınız varsa, bildirim sırasında onu mut
anahtar kelimesini kullanarak açıkça değişebilir olarak işaretlemelisiniz.
let mut sayac = 0; // 'sayac'ı değişebilir olarak bildir
println!("Başlangıç sayacı: {}", sayac);
sayac = 1; // 'sayac' 'mut' ile bildirildiği için buna izin verilir
println!("Yeni sayaç: {}", sayac);
Rust ayrıca gölgelemeye izin verir. Aynı kapsam içinde önceki bir değişkenle aynı ada sahip yeni bir değişken bildirebilirsiniz. Yeni değişken eskisini “gölgeler”, yani adın sonraki kullanımları yeni değişkene atıfta bulunur. Bu, tamamen yeni bir değişken oluşturduğumuz için mutasyondan farklıdır ve bu değişkenin farklı bir tipi bile olabilir.
let bosluklar = " "; // 'bosluklar' başlangıçta bir dizi dilimidir (&str)
let bosluklar = bosluklar.len(); // 'bosluklar' şimdi uzunluğu tutan yeni bir değişken tarafından gölgeleniyor (bir tam sayı, usize)
println!("Boşluk sayısı: {}", bosluklar); // Tam sayı değerini yazdırır
Rust statik tipli bir dildir. Bu, her değişkenin tipinin derleme zamanında derleyici tarafından bilinmesi gerektiği anlamına gelir. Ancak, Rust'ın mükemmel tip çıkarımı vardır. Çoğu durumda, tipi açıkça yazmanız gerekmez; derleyici genellikle değere ve onu nasıl kullandığınıza göre bunu anlayabilir.
let miktar = 10; // Derleyici i32 (varsayılan işaretli tam sayı tipi) çıkarımı yapar
let fiyat = 9.99; // Derleyici f64 (varsayılan kayan noktalı sayı tipi) çıkarımı yapar
let aktif = true; // Derleyici bool (boolean) çıkarımı yapar
let bas_harf = 'R'; // Derleyici char (karakter) çıkarımı yapar
Açık olmak isterseniz veya buna ihtiyacınız varsa (örneğin, netlik için veya derleyicinin yardıma ihtiyacı olduğunda), iki nokta üst üste :
ve ardından tip adını kullanarak tip belirtimleri sağlayabilirsiniz.
let skor: i32 = 100; // Açıkça işaretli 32-bit tam sayı
let oran: f32 = 0.5; // Açıkça tek duyarlıklı kayan noktalı sayı
let tamamlandi_mi: bool = false; // Açıkça boolean
let not: char = 'A'; // Açıkça bir karakter (Unicode skaler değeri)
Rust'ın birkaç yerleşik skaler tipi (tek değerleri temsil eden) vardır:
i8
, i16
, i32
, i64
, i128
, isize
) hem pozitif hem de negatif tam sayıları saklar. İşaretsiz tam sayılar (u8
, u16
, u32
, u64
, u128
, usize
) yalnızca negatif olmayan tam sayıları saklar. isize
ve usize
tipleri bilgisayarın mimarisine (32-bit veya 64-bit) bağlıdır ve öncelikle koleksiyonları indekslemek için kullanılır.f32
(tek duyarlıklı) ve f64
(çift duyarlıklı). Varsayılan f64
'tür.bool
tipinin iki olası değeri vardır: true
veya false
.char
tipi tek bir Unicode skaler değerini temsil eder (sadece ASCII karakterlerinden daha kapsamlıdır), tek tırnak içine alınır (örneğin, 'z'
, 'π'
, '🚀'
).String
vs &str
Rust'ta metin işlemek genellikle yeni başlayanlar için kafa karıştırıcı olabilen iki ana tipi içerir:
&str
(“dizi dilimi” olarak telaffuz edilir): Bu, bellekte bir yerde saklanan UTF-8 kodlu bayt dizisine değişmez bir referanstır. Dizi sabitleri ( "Merhaba"
gibi) &'static str
tipindedir, yani doğrudan programın ikili dosyasında saklanırlar ve programın tüm süresi boyunca yaşarlar. Dilimler, dizi (string) verilerine sahip olmadan bir görünüm sağlar. Boyutları sabittir.String
: Bu, sahiplenilmiş, büyüyebilir, değişebilir, UTF-8 kodlu bir dizi (string) tipidir. String
verileri yığında (heap) saklanır, bu da yeniden boyutlandırılmasına olanak tanır. Genellikle dizi verilerini değiştirmeniz gerektiğinde veya dizinin kendi verilerine sahip olması ve kendi yaşam süresini yönetmesi gerektiğinde (genellikle fonksiyonlardan dizileri döndürürken veya bunları struct'larda saklarken) String
kullanırsınız.// Dizi sabiti (program ikili dosyasında saklanır, değişmez)
let statik_dilim: &'static str = "Ben değişmezim";
// Bir sabitten sahiplenilmiş, yığında ayrılmış bir String oluştur
let mut dinamik_dizi: String = String::from("Başla");
// String'i değiştir (değişebilir olduğu ve verilerine sahip olduğu için mümkün)
dinamik_dizi.push_str(" ve büyü");
println!("{}", dinamik_dizi); // Çıktı: Başla ve büyü
// String'in bir kısmına referans veren bir dizi dilimi oluştur
// Bu dilim, dinamik_dizi'den veri ödünç alır
let dizeden_dilim: &str = &dinamik_dizi[0..5]; // "Başla"ya referans verir
println!("Dilim: {}", dizeden_dilim);
Fonksiyonlar, kodu adlandırılmış, yeniden kullanılabilir birimler halinde düzenlemek için temeldir. Özel main
fonksiyonuyla zaten karşılaştık.
// Fonksiyon tanımı
fn selamla(isim: &str) { // Bir parametre alır: 'isim', bir dizi dilimidir (&str)
println!("Merhaba, {}!", isim);
}
// İki i32 parametresi alan ve bir i32 döndüren fonksiyon
fn topla(a: i32, b: i32) -> i32 {
// Rust'ta, bir fonksiyon gövdesindeki son ifade,
// noktalı virgülle bitmediği sürece otomatik olarak döndürülür.
a + b
// Bu şuna eşdeğerdir: return a + b;
}
fn main() {
selamla("Alice"); // 'selamla' fonksiyonunu çağır
let toplam = topla(5, 3); // 'topla'yı çağır, döndürülen değeri 'toplam'a bağla
println!("5 + 3 = {}", toplam); // Çıktı: 5 + 3 = 8
}
Fonksiyonlarla ilgili önemli noktalar:
fn
anahtar kelimesini kullanın.->
işaretinden sonra belirtin. Bir fonksiyon değer döndürmezse, dönüş tipi örtük olarak ()
'dır (boş bir demet, genellikle “birim tipi” olarak adlandırılır).;
ile biten talimatlar) oluşur ve isteğe bağlı olarak bir deyim (bir değere değerlendirilen bir şey) ile biter.return
anahtar kelimesi, fonksiyonun herhangi bir yerinden açık, erken dönüşler için kullanılabilir.Rust, kodun hangi sırayla yürütüleceğini belirlemek için standart kontrol akış yapıları sağlar:
if
/else
/else if
: Koşullu yürütme için kullanılır.let sayi = 6;
if sayi % 4 == 0 {
println!("sayı 4'e bölünebilir");
} else if sayi % 3 == 0 {
println!("sayı 3'e bölünebilir"); // Bu dal yürütülür
} else {
println!("sayı 4 veya 3'e bölünemez");
}
// Önemli olarak, 'if' Rust'ta bir deyimdir, yani bir değere değerlendirilir.
// Bu, onu doğrudan 'let' ifadelerinde kullanmanıza olanak tanır.
let kosul = true;
let deger = if kosul { 5 } else { 6 }; // deger 5 olacaktır
println!("Değer: {}", deger);
// Not: 'if' deyiminin her iki dalı da aynı tipe değerlendirilmelidir.
loop
: Sonsuz bir döngü oluşturur. Döngüden çıkmak için genellikle break
kullanırsınız, isteğe bağlı olarak bir değer döndürebilirsiniz.while
: Belirtilen bir koşul doğru kaldığı sürece döngü yapar.for
: Bir koleksiyonun veya bir aralığın öğeleri üzerinde yinelenir. Bu, Rust'ta en sık kullanılan ve genellikle en güvenli döngü türüdür.// loop örneği
let mut sayac = 0;
let sonuc = loop {
sayac += 1;
if sayac == 10 {
break sayac * 2; // Döngüden çık ve 'sayac * 2' döndür
}
};
println!("Döngü sonucu: {}", sonuc); // Çıktı: Döngü sonucu: 20
// while örneği
let mut num = 3;
while num != 0 {
println!("{}!", num);
num -= 1;
}
println!("FIRLAT!!!");
// for örneği (bir dizi üzerinde yineleme)
let a = [10, 20, 30, 40, 50];
for eleman in a.iter() { // .iter() dizinin elemanları üzerinde bir yineleyici oluşturur
println!("değer: {}", eleman);
}
// for örneği (bir aralık üzerinde yineleme)
// (1..4) 1, 2, 3'ü içeren bir aralık oluşturur (4 hariç)
// .rev() yineleyiciyi tersine çevirir
for sayi in (1..4).rev() {
println!("{}!", sayi); // 3!, 2!, 1! yazdırır
}
println!("TEKRAR FIRLAT!!!");
Derleyicinin yok sayacağı açıklamalar ve notlar eklemek için yorumları kullanın.
// Bu tek satırlık bir yorumdur. Satırın sonuna kadar uzanır.
/*
* Bu çok satırlı, blok bir yorumdur.
* Birkaç satıra yayılabilir ve daha uzun açıklamalar için
* kullanışlıdır.
*/
let sansli_sayi = 7; // Yorumları bir satırın sonuna da yerleştirebilirsiniz.
Sahiplik, Rust'ın en belirgin ve merkezi özelliğidir. Rust'ın bir çöp toplayıcıya ihtiyaç duymadan derleme zamanında bellek güvenliğini garanti etmesini sağlayan mekanizmadır. Sahipliği kavramak, Rust'ı anlamanın anahtarıdır. Üç temel kuralı takip eder:
{ // s burada geçerli değil, henüz bildirilmedi
let s = String::from("merhaba"); // s bu noktadan itibaren geçerlidir;
// s yığında (heap) ayrılan String verisine 'sahiptir'.
// s'yi burada kullanabilirsiniz
println!("{}", s);
} // Kapsam burada sona erer. 's' artık geçerli değildir.
// Rust, 's'nin sahip olduğu String için otomatik olarak özel bir 'drop' fonksiyonu çağırır,
// yığın belleğini serbest bırakır.
Sahiplenilmiş bir değeri (bir String
, Vec
veya sahiplenilmiş tipler içeren bir struct gibi) başka bir değişkene atadığınızda veya değere göre bir fonksiyona geçirdiğinizde, sahiplik taşınır. Orijinal değişken geçersiz hale gelir.
let s1 = String::from("orijinal");
let s2 = s1; // String verisinin sahipliği s1'den s2'ye TAŞINDI.
// s1 bu noktadan sonra artık geçerli sayılmaz.
// println!("s1: {}", s1); // Derleme zamanı hatası! Taşıma işleminden sonra değer burada ödünç alındı.
// s1 artık verilere sahip değil.
println!("s2: {}", s2); // s2 şimdi sahibidir ve geçerlidir.
Bu taşıma davranışı, iki değişkenin kapsam dışına çıktıklarında yanlışlıkla aynı bellek konumunu serbest bırakmaya çalıştığı “çift serbest bırakma” hatalarını önler. Tam sayılar, kayan noktalı sayılar, booleanlar ve karakterler gibi ilkel tipler Copy
trait'ini uygular, yani atandıklarında veya fonksiyonlara geçirildiklerinde taşınmak yerine basitçe kopyalanırlar.
Bir fonksiyonun sahipliği devretmeden bir değeri kullanmasını isterseniz ne olur? Referanslar oluşturabilirsiniz. Bir referans oluşturmaya ödünç alma denir. Bir referans, başka bir değişkenin sahip olduğu verilere sahipliğini almadan erişmenizi sağlar.
// Bu fonksiyon bir String'e referans (&) alır.
// String'i ödünç alır ancak sahipliğini almaz.
fn uzunlugu_hesapla(s: &String) -> usize {
s.len()
} // Burada, s (referans) kapsam dışına çıkar. Ancak String verisine sahip olmadığı için,
// referans kapsam dışına çıktığında veriler BIRAKILMAZ.
fn main() {
let s1 = String::from("merhaba");
// '&' sembolünü kullanarak s1'e bir referans iletiyoruz.
// s1 hala String verisine sahiptir.
let len = uzunlugu_hesapla(&s1);
// Sahiplik hiçbir zaman taşınmadığı için s1 burada hala geçerlidir.
println!("'{}' uzunluğu {}.", s1, len);
}
Referanslar, tıpkı değişkenler gibi varsayılan olarak değişmezdir. Ödünç alınan verileri değiştirmek isterseniz, &mut
ile gösterilen değişebilir bir referansa ihtiyacınız vardır. Ancak Rust, veri yarışlarını önlemek için değişebilir referanslar etrafında katı kurallar uygular:
Ödünç Alma Kuralları:
&mut T
).&T
).Bu kurallar derleyici tarafından zorlanır.
// Bu fonksiyon bir String'e değişebilir bir referans alır
fn degistir(bir_dizi: &mut String) {
bir_dizi.push_str(", dünya");
}
fn main() {
// Değişebilir ödünç almaya izin vermek için 's' değişebilir olarak bildirilmelidir
let mut s = String::from("merhaba");
// Ödünç alma kuralı uygulamasının örneği (hataları görmek için satırların yorumunu kaldırın):
// let r1 = &s; // değişmez ödünç alma - TAMAM
// let r2 = &s; // başka bir değişmez ödünç alma - TAMAM (birden çok değişmez ödünç almaya izin verilir)
// let r3 = &mut s; // HATA! Değişmez ödünç almalar etkinken `s` değişebilir olarak ödünç alınamaz
// // Rust zorlar: ya birden çok okuyucu (&T) YA DA tek yazıcı (&mut T), asla ikisi birden olmaz
// println!("{}, {}", r1, r2); // r1/r2'yi kullanmak onları aktif tutar ve hatayı tetikler
// // Bu println olmadan, Rust'ın NLL'si (Non-Lexical Lifetimes) r1/r2'yi erken bırakırdı,
// // &mut s'yi burada geçerli kılardı
// Başka ödünç alma aktif olmadığı için burada değişebilir bir ödünç almaya izin verilir
degistir(&mut s);
println!("{}", s); // Çıktı: merhaba, dünya
}
Rust, birden çok değeri daha karmaşık tipler halinde gruplamanın yollarını sunar.
Struct'lar (yapılar için kısaltma), ilgili veri alanlarını tek bir ad altında gruplayarak özel veri tipleri tanımlamanıza olanak tanır.
// User adında bir struct tanımla
struct User {
active: bool,
username: String, // Sahiplenilmiş String tipini kullanır
email: String,
sign_in_count: u64,
}
fn main() {
// User struct'ının bir örneğini oluştur
// Örnekler tüm alanlar için değer sağlamalıdır
let mut user1 = User {
email: String::from("biri@ornek.com"),
username: String::from("birkullaniciadi123"),
active: true,
sign_in_count: 1,
};
// Struct alanlarına nokta gösterimi kullanarak eriş
// Alan değerlerini değiştirmek için örnek değişebilir olmalıdır
user1.email = String::from("baskaeposta@ornek.com");
println!("Kullanıcı e-postası: {}", user1.email);
// Bir User örneği oluşturmak için yardımcı bir fonksiyon kullanma
let user2 = build_user(String::from("user2@test.com"), String::from("user2"));
println!("User 2 aktif durumu: {}", user2.active);
// Struct güncelleme sözdizimi: Kalan alanlar için mevcut bir örnekten
// bazı alanları kullanarak yeni bir örnek oluşturur.
let user3 = User {
email: String::from("user3@domain.com"),
username: String::from("user3"),
..user2 // 'active' ve 'sign_in_count' değerlerini user2'den alır
};
println!("User 3 oturum açma sayısı: {}", user3.sign_in_count);
}
// Bir User örneği döndüren fonksiyon
fn build_user(email: String, username: String) -> User {
User {
email, // Alan başlatma kısayolu: parametre adı alan adıyla eşleşiyorsa
username,
active: true,
sign_in_count: 1,
}
}
Rust ayrıca demet struct'ları (adlandırılmış demetler, örn. struct Color(i32, i32, i32);
) ve birim benzeri struct'ları (hiçbir alanı olmayan ve bir tip üzerinde bir trait uygulamanız gerektiğinde ancak herhangi bir veri saklamanız gerekmediğinde kullanışlıdır, örn. struct AlwaysEqual;
) destekler.
Enum'lar (numaralandırmalar), olası varyantlarını numaralandırarak bir tip tanımlamanıza olanak tanır. Bir enum değeri yalnızca olası varyantlarından biri olabilir.
// IP adresi türlerini tanımlayan basit enum
enum IpAddrKind {
V4, // Varyant 1
V6, // Varyant 2
}
// Enum varyantları ilişkili veriler de tutabilir
enum IpAddr {
V4(u8, u8, u8, u8), // V4 varyantı dört u8 değeri tutar
V6(String), // V6 varyantı bir String tutar
}
// Rust'ın standart kütüphanesinde çok yaygın ve önemli bir enum: Option<T>
// Mevcut olabilecek veya olmayabilecek bir değer kavramını kodlar.
// enum Option<T> {
// Some(T), // T tipinde bir değerin varlığını temsil eder
// None, // Bir değerin yokluğunu temsil eder
// }
// Başka bir önemli standart kütüphane enum'u: Result<T, E>
// Başarılı (Ok) veya başarısız (Err) olabilecek işlemler için kullanılır.
// enum Result<T, E> {
// Ok(T), // Başarıyı temsil eder, T tipinde bir değer içerir
// Err(E), // Başarısızlığı temsil eder, E tipinde bir hata değeri içerir
// }
fn main() {
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
// İlişkili verilerle IpAddr enum'unun örneklerini oluşturma
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
// Option<T> ile örnek
let some_number: Option<i32> = Some(5);
let no_number: Option<i32> = None;
// 'match' kontrol akışı operatörü enum'larla çalışmak için mükemmeldir.
// Enum varyantına göre farklı kod yürütmenizi sağlar.
match some_number {
Some(i) => println!("Bir sayı alındı: {}", i), // Eğer Some ise, iç değeri i'ye bağla
None => println!("Hiçbir şey alınmadı."), // Eğer None ise
}
// 'match' kapsamlı olmalıdır: tüm olası varyantları ele almalısınız.
// Alt çizgi '_' açıkça listelenmeyen varyantları yakalamak için
// bir joker karakter deseni olarak kullanılabilir.
}
Option<T>
ve Result<T, E>
, Rust'ın potansiyel olarak eksik değerleri ve hataları sağlam bir şekilde ele alma yaklaşımının merkezinde yer alır.
Cargo, Rust projelerini derleme, test etme ve yönetme sürecini kolaylaştıran Rust ekosisteminin vazgeçilmez bir parçasıdır. Geliştiricilerin sıklıkla övdüğü özelliklerden biridir.
Cargo.toml
: Bu, Rust projenizin manifest dosyasıdır. TOML (Tom's Obvious, Minimal Language) formatında yazılmıştır. Projeniz hakkında temel meta verileri (adı, sürümü ve yazarları gibi) ve en önemlisi bağımlılıklarını (projenizin güvendiği diğer harici crate'ler) listeler.
[package]
name = "my_project"
version = "0.1.0"
edition = "2021" # Kullanılacak Rust sürümünü belirtir (dil özelliklerini etkiler)
# Bağımlılıklar aşağıda listelenir
[dependencies]
# Örnek: Rastgele sayı üretimi için 'rand' crate'ini ekleyin
# rand = "0.8.5"
# Derlediğinizde, Cargo 'rand' ve bağımlılıklarını indirip derleyecektir.
cargo new <proje_adi>
: Yeni bir ikili (çalıştırılabilir) uygulama proje yapısı oluşturur.cargo new --lib <kutuphane_adi>
: Yeni bir kütüphane (diğer programlar tarafından kullanılması amaçlanan crate) proje yapısı oluşturur.cargo build
: Projenizi ve bağımlılıklarını derler. Varsayılan olarak, optimize edilmemiş bir hata ayıklama derlemesi oluşturur. Çıktı target/debug/
dizinine yerleştirilir.cargo build --release
: Projenizi optimizasyonlar etkinleştirilmiş olarak derler, dağıtım veya performans testi için uygundur. Çıktı target/release/
dizinine yerleştirilir.cargo run
: İkili projenizi derler (gerekirse) ve çalıştırır.cargo check
: Kodunuzu derleme hataları açısından hızlıca kontrol eder, ancak son çalıştırılabilir dosyayı üretmez. Bu genellikle cargo build
'dan çok daha hızlıdır ve hızlı geri bildirim için geliştirme sırasında kullanışlıdır.cargo test
: Projeniz içinde tanımlanan tüm testleri çalıştırır (genellikle src
dizininde veya ayrı bir tests
dizininde bulunur).Cargo.toml
dosyanıza bir bağımlılık eklediğinizde ve ardından cargo build
veya cargo run
gibi bir komut çalıştırdığınızda, Cargo merkezi depo crates.io'dan gerekli crate'i (ve onun bağımlılıklarını) indirmeyi ve her şeyi birlikte derlemeyi otomatik olarak halleder.
Bu başlangıç kılavuzu, başlamanız için mutlak temelleri kapsamıştır. Rust dili, ilerledikçe keşfedilecek çok daha güçlü özellikler sunar:
Result
enum'unda ustalaşma, ?
operatörünü kullanarak hata yayma ve özel hata tipleri tanımlama.Vec<T>
(dinamik diziler/vektörler), HashMap<K, V>
(hash haritaları), HashSet<T>
vb. gibi yaygın veri yapılarıyla etkili bir şekilde çalışma.<T>
) kullanarak farklı veri tipleri üzerinde çalışabilen esnek, yeniden kullanılabilir kod yazma.'a
) gerektirir.Mutex
ve Arc
ile paylaşılan durumu ve Rust'ın asenkron programlama için güçlü async
/await
sözdizimini keşfetme.Rust benzersiz ve ilgi çekici bir öneri sunar: C++ gibi alt seviye dillerden beklenen ham performans, özellikle bellek yönetimi ve eşzamanlılık etrafındaki yaygın hataların tüm sınıflarını ortadan kaldıran güçlü derleme zamanı güvenlik garantileriyle birleştirilmiştir. Öğrenme eğrisi, sahiplik ve ödünç alma gibi yeni kavramları içselleştirmeyi (ve bazen katı olan derleyiciyi dinlemeyi) içerse de, bunun karşılığı son derece güvenilir, verimli ve uzun vadede bakımı genellikle daha kolay olan yazılımdır. Cargo aracılığıyla mükemmel araçları ve destekleyici topluluğu ile Rust, öğrenmesi ödüllendirici bir dildir.
Küçük başlayın, Cargo kullanarak deneyler yapın, derleyicinin yardımcı (bazen ayrıntılı olsa da) hata mesajlarını rehberlik olarak benimseyin ve bu güçlü ve giderek daha popüler hale gelen dilde ustalaşma yolunda emin adımlarla ilerleyeceksiniz. Mutlu Rustlamalar!