عند كتابة وظائف عامة في Go، قد يكون من المفيد قبول أنواع ملموسة أيضًا. ومع ذلك، فإن هذا يشكل تحديًا عند محاولة تهيئة شرائح من الواجهات بمثيلات جديدة من تلك الأنواع المحددة.
قد يبدو أحد الأساليب منطقيًا: تحديد معلمتين من النوع، واحد لنوع عنصر الشريحة (X) والآخر لنوع الخرسانة (Y) لإنشاء مثيل له. ومع ذلك، يفشل هذا الأسلوب عند محاولة تعيين مثيل Y لعنصر من النوع X.
func Fill[X, Y any](slice []X){
for i := range slice {
slice[i] = new(Y) // not work!
}
}
تنشأ هذه المشكلة لأن المترجم يفقد العلاقة بين الواجهة X وتنفيذها Y. يتم التعامل مع كل من X وY على أنهما مختلفان من أي نوع.
لمعالجة هذا الأمر، يمكن للمرء استخدام عملية صب صريحة داخل الوظيفة:
func Fill[X, Y any](slice []X) {
for i := range slice {
slice[i] = any(*new(Y)).(X)
}
}
ومع ذلك، فإن هذا الأسلوب يثير حالة من الذعر إذا لم يقم Y بتنفيذ X، وهو ما يحدث في سيناريوهات مثل محاولة تعيين *sync.Mutex (نوع المؤشر) لمزامنة.Locker.
يتضمن الحل الأكثر قوة وأمانًا للنوع استخدام وظيفة المنشئ:
func Fill[X any](slice []X, f func() X) {
for i := range slice {
slice[i] = f()
}
}
تقبل هذه الوظيفة دالة منشئة تقوم بإرجاع مثيل جديد من النوع المحدد. يسمح هذا بتهيئة موجزة وآمنة للشرائح بمثيلات من النوع الملموس.
في الحالات التي يكون فيها النوع الملموس مقصودًا أن يتم إنشاء مثيل له بنوع المؤشر، من المهم ملاحظة ذلك أن new(Y) سيؤدي إلى قيمة صفر. للتحايل على ذلك، يمكن ضبط الدالة المُنشئة لإرجاع قيمة المؤشر الصحيحة، مثل func() X { return &sync.Mutex{} }.
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3