أهم أخطاء مطوري Rust المبتدئين: من الألف إلى الياء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

أهم أخطاء مطوري Rust المبتدئين: من الألف إلى الياء

\n\n

Rust هي لغة برمجة قوية وآمنة، لكن نظام الملكية والاقتراض الصارم فيها غالبًا ما يربك المبتدئين. في هذه المقالة، سنحلل الأخطاء الأكثر شيوعًا التي يواجهها المطورون المبتدئون في Rust. كل خطأ مصحوب بمثال كود، وشرح، وحل صحيح. هيا بنا!

\n\n

1. تجاهل نظام الملكية (Ownership)

\n\n

الخطأ الأكثر شيوعًا هو محاولة استخدام قيمة بعد نقلها. في Rust، يمكن أن يكون لكل قيمة مالك واحد فقط.

\n\n

❌ كود خاطئ:

\n
fn main() {\n    let s1 = String::from("مرحباً");\n    let s2 = s1;\n    println!("{}", s1); // خطأ! s1 لم يعد يملك السلسلة النصية\n}\n
\n\n

✅ الحل الصحيح:

\n
fn main() {\n    let s1 = String::from("مرحباً");\n    let s2 = s1.clone(); // نسخ صريح\n    println!("{}", s1); // يعمل الآن\n    println!("{}", s2);\n}\n
\n\n

نصيحة: استخدم .clone() فقط عندما يكون ذلك ضروريًا حقًا. بالنسبة للأنواع البدائية (i32, bool)، يتم النسخ تلقائيًا.

\n\n

2. الخلط بين String و &str

\n\n

غالبًا لا يفهم المبتدئون الفرق بين السلسلة المملوكة String والشريحة النصية &str. يؤدي هذا إلى أخطاء عند تمرير السلاسل النصية إلى الدوال.

\n\n

❌ كود خاطئ:

\n
fn print_message(msg: String) {\n    println!("{}", msg);\n}\n\nfn main() {\n    let greeting = "مرحباً بكم"; // &str\n    print_message(greeting); // خطأ! يُتوقع String\n}\n
\n\n

✅ الحل الصحيح:

\n
fn print_message(msg: &str) {\n    println!("{}", msg);\n}\n\nfn main() {\n    let greeting = "مرحباً بكم";\n    print_message(greeting); // يعمل!\n    \n    let owned = String::from("العالم");\n    print_message(&owned); // &String يتحول تلقائيًا إلى &str\n}\n
\n\n

القاعدة الذهبية: في معاملات الدوال، استخدم &str إذا لم تكن بحاجة لنقل ملكية السلسلة النصية.

\n\n

3. انتهاك قواعد الاقتراض (Borrowing)

\n\n

لا يسمح Rust بوجود مراجع قابلة للتغيير وغير قابلة للتغيير في نفس الوقت لنفس الكائن. هذا يحمي من سباقات البيانات.

\n\n

❌ كود خاطئ:

\n
fn main() {\n    let mut data = vec![1, 2, 3];\n    let ref1 = &data;\n    let ref2 = &mut data; // خطأ! يوجد بالفعل مرجع غير قابل للتغيير\n    println!("{}", ref1);\n}\n
\n\n

✅ الحل الصحيح:

\n
fn main() {\n    let mut data = vec![1, 2, 3];\n    {\n        let ref1 = &data;\n        println!("{}", ref1); // ref1 يعيش فقط في هذا الكتلة\n    } // ref1 يخرج من النطاق\n    let ref2 = &mut data; // الآن يمكن\n    ref2.push(4);\n    println!("{:?}", ref2);\n}\n
\n\n

هام: ينتهي نطاق المرجع عند آخر استخدام له. مترجم Rust ذكي بما يكفي لتتبع ذلك.

\n\n

4. مشاكل مع زمن الحياة (Lifetimes)

\n\n

الأخطاء المتعلقة بتعليقات زمن الحياة تخيف المبتدئين أكثر من غيرها. الأكثر شيوعًا هو إرجاع مرجع لمتغير محلي.

\n\n

❌ كود خاطئ:

\n
fn get_reference() -> &str {\n    let local = String::from("اختبار");\n    &local // خطأ! سيتم تدمير local بعد الخروج من الدالة\n}\n
\n\n

✅ الحل الصحيح (عبر الملكية):

\n
fn get_reference() -> String {\n    let local = String::from("اختبار");\n    local // نعيد الملكية\n}\n\nfn main() {\n    let s = get_reference();\n    println!("{}", s);\n}\n
\n\n

✅ الحل الصحيح (عبر المعامل):

\n
fn get_reference<'a>(input: &'a str) -> &'a str {\n    input // نعيد المرجع بنفس زمن الحياة\n}\n\nfn main() {\n    let data = String::from("اختبار");\n    let result = get_reference(&data);\n    println!("{}", re                

المدونات

توصيات الكتب