مقدمة: لماذا سؤال "How to assign string to bytes array" شائع جدًا؟
\n\nإذا كنت قد كتبت يومًا بلغة Go (Golang) وواجهت الحاجة لتحويل سلسلة نصية عادية إلى مصفوفة بايت ([]byte)، فأنت لست وحدك. سؤال "How to assign string to bytes array" على Stack Overflow يجمع عشرات الآلاف من المشاهدات. قد يبدو الأمر بسيطًا؟ خذها وأسندها. لكن Go هي لغة ذات كتابة صارمة، ولا يمكنك ببساطة أخذ سلسلة نصية وإسنادها إلى شريحة بايت. تحتاج إلى معرفة التقنيات الصحيحة.
في هذه المقالة، سنشرح تحويل string إلى bytes array في Go. سأعرض لكم ثلاث طرق رئيسية: بدءًا من الأبسط وصولاً إلى الأسرع جدًا ولكن الخطير. ستتعلم أي طريقة تختار حسب المهمة، وستتوقف نهائيًا عن الخلط في هذه التحويلات.
\n\nهيا بنا!
\n\nالقليل من النظرية: لماذا السلسلة النصية ليست مصفوفة بايت؟
\n\nقبل الاندفاع إلى الكود، دعنا نفهم لماذا تميز Go بين هذين النوعين. هذه المعرفة ستنقذك من عشرات الأخطاء.
\n\n- \n
- string في Go هي تسلسل بايت غير قابل للتغيير (immutable). لا يمكنك تغيير حرف السلسلة حسب الفهرس. يتم تخزين السلسلة دائمًا ككتلة ذاكرة للقراءة فقط. \n
- []byte هي شريحة بايت قابلة للتغيير (mutable). يمكنك تغيير محتواها، إضافة عناصر جديدة، إلخ. \n
بسبب هذا الاختلاف في "عدم القابلية للتغيير"، تتطلب Go تحويلًا صريحًا. إذا سمح المترجم ببساطة بإسناد سلسلة نصية إلى مصفوفة بايت، فقد تتمكن عن طريق الخطأ من تغيير البيانات "المحمية" للسلسلة. لذلك، assign string to bytes array يتطلب دائمًا إجراءً واعيًا منك.
\n\nالطريقة رقم 1: التحويل الصريح للنوع (الأبسط)
\n\nهذه هي الطريقة الأولى التي تتبادر إلى ذهن كل مبتدئ. وهي تعمل!
\n\npackage main\n\nimport "fmt"\n\nfunc main() {\n myString := "مرحبًا، Go!"\n myBytes := []byte(myString)\n\n fmt.Println(myBytes) // [208 159 209 128 ...] — بايتات UTF-8\n fmt.Println(string(myBytes)) // نعيدها: "مرحبًا، Go!"\n}\n\n\nالإيجابيات:
\n- \n
- بسيط للغاية وقابل للقراءة. \n
- طريقة قياسية، مفهومة لأي مطور Go. \n
السلبيات:
\n- \n
- ينشئ نسخة جديدة من البيانات في الذاكرة. إذا كانت السلسلة كبيرة جدًا (مثلاً 10 ميجابايت)، فقد يكون ذلك مكلفًا من حيث الذاكرة والوقت. \n
- غير مناسب للأنظمة عالية التحميل حيث تكون كل نانوثانية مهمة. \n
متى تستخدم: في 90% من الحالات. للتطبيقات العادية، خدمات الويب، والبرامج النصية، هذا أكثر من كافٍ. لا تقم بتحسين ما لا يحتاج إلى تحسين.
\n\nالطريقة رقم 2: استخدام copy() (مسيطر عليه)
\n\nأحيانًا يكون لديك مصفوفة بايت مخصصة مسبقًا، وتريد ملؤها ببيانات من سلسلة نصية. هنا تأتي وظيفة copy للإنقاذ.
package main\n\nimport "fmt"\n\nfunc main() {\n myString := "Go is awesome"\n \n // إنشاء شريحة بايت بالطول المطلوب\n myBytes := make([]byte, len(myString))\n \n // نسخ البيانات من السلسلة إلى الشريحة\n n := copy(myBytes, myString)\n \n fmt.Printf("تم نسخ البايتات: %d\\n", n) // 13\n fmt.Println(string(myBytes)) // "Go is awesome"\n}\n\n\nلاحظ: copy ينسخ فقط عدد البايتات التي تتسع في الشريحة الهدف. إذا كانت الشريحة الهدف أقصر من السلسلة، سيتم نسخ طولها فقط. هذا أكثر أمانًا من التحويل الصريح إذا لم تكن متأكدًا من الحجم.
الإيجابيات:
\n- \n
- تحكم كامل في عملية النسخ. \n
- الأمان: لن تتجاوز حدود المصفوفة. \n
- يمكن استخدامه للنسخ الجزئي (substring). \n
السلبيات:
\n- \n
- يتطلب تخصيص ذاكرة مسبقًا (
make). \n - مع ذلك يتم إنشاء نسخة من البيانات.