إنشاء تطبيقات لأنواع عامة في Go

يحتوي Go على أنواع قوية وثابتة ولا يدعم الأدوية الجنيسة ، فكيف يمكننا تحديد هياكل وخوارزميات بيانات الأغراض العامة التي يمكن تطبيقها على أكثر من نوع واحد؟interface{}s ليست الحل ، لأنها تتطلب الإرسال ونفقد الكثير من مزايا الكتابة الثابتة القوية.الحل هو توليد الكود، لأنه يسمح بالحصول على فحوصات وقت التجميع والسلامة ، وأداء أعلى.

لم أجد هذه المعلومات يمكن الوصول إليها بسهولة عند البحث عن موضوعات إنشاء الكود ، لكنني عثرت على حالات وسيناريوهات استخدام أكثر تعقيدًا ، لذا ها هي موضحة باللغة الإنجليزية البسيطة.

مشكلة:

أريد أنتنفيذ بنية البيانات(الأمر نفسه ينطبق على الخوارزمية)بأكثر الطرق عموميةمع Go و وإنشاء تطبيقات خاصة بالنوع يمكنني إعادة استخدامها بسهولة.

المحلول:

استخدامجيني، لا يمكن أن يكون هذا أبسط:

  1. يستوردgenny/generic
  2. حدد نوعًا واحدًا أو أكثر مثلgeneric.Type، على سبيل المثال الاتصال بهمItemأوType
  3. استخدم هذه الأنواع في التعليمات البرمجية الخاصة بك
  4. يركضgennyلإنشاء التنفيذ الخاص بالنوع

مثال

تحقق من هذا المثال البسيط ، وهو إصدار مقتطع من ملفتعيين تنفيذ بنية البيانات في Go:

// Package set creates a ItemSet data structure for the Item type
package set

import github.com/cheekybits/genny/generic

// Item the type of the Set type Item generic.Type

// ItemSet the set of Items type ItemSet struct { items map[Item]bool }

// Add adds a new element to the Set. Returns the Set. func (s ItemSet) Add(t Item) ItemSet { if s.items == nil { s.items = make(map[Item]bool) } _, ok := s.items[t] if !ok { s.items[t] = true } return s }

// Clear removes all elements from the Set func (s ItemSet) Clear() { (s).items = make(map[Item]bool) }

عن طريق الركض

genny -in set.go -out gen-set.go gen "Item=string,int"

في سطر الأوامر الآن ، إذا تم استدعاء الملفset.goسوف تولدgen-set.goوالتي تحتوي على ما يلي:

// This file was automatically generated by genny.
// Any changes will be lost if this file is regenerated.
// see https://github.com/cheekybits/genny

// Package Set creates a StringSet data structure for the string type
package set

// StringSet the set of Strings type StringSet struct { items map[string]bool }

// Add adds a new element to the Set. Returns the Set. func (s StringSet) Add(t string) StringSet { s.items[t] = true return s }

// Clear removes all elements from the Set func (s StringSet) Clear() { (s).items = make(map[string]bool) }

// Delete removes the string from the Set and returns Has(string) func (s StringSet) Delete(item string) bool { ret := (s).Has(item) if ret { delete((*s).items, item) } return ret }

// Has returns true if the Set contains the string func (s StringSet) Has(item string) bool { return (s).items[item] }

// Strings returns the string(s) stored func (s *StringSet) Strings() []string { items := []string{} for i := range s.items { items = append(items, i) } return items }

// Package Set creates a IntSet data structure for the int type // IntSet the set of Ints type IntSet struct { items map[int]bool }

// Add adds a new element to the Set. Returns the Set. func (s IntSet) Add(t int) IntSet { s.items[t] = true return s }

// Clear removes all elements from the Set func (s IntSet) Clear() { (s).items = make(map[int]bool) }

// Delete removes the int from the Set and returns Has(int) func (s IntSet) Delete(item int) bool { ret := (s).Has(item) if ret { delete((*s).items, item) } return ret }

// Has returns true if the Set contains the int func (s IntSet) Has(item int) bool { return (s).items[item] }

// Ints returns the int(s) stored func (s *IntSet) Ints() []int { items := []int{} for i := range s.items { items = append(items, i) } return items }

كما ترون،gennyخلقStringSetوIntSetالهياكل منItemSet** ، لأن روى ذلكItem=string,int.

كما أنها خلقت أساليب الهيكلالتي تؤلف تطبيقات المجموعة لدينا.

إذا أردنا إضافة مجموعة أخرى من الأنواع إلى تطبيقنا ، فيمكننا تعديل الأمر وتشغيله مرة أخرى.

يستخدمgo generate

يمكنك أيضًا أتمتة ذلك عن طريق إضافة تعليق أعلى الملف ، أسفل مستند الحزمة ، مثل:

// go:generate genny -in=$GOFILE -out=gen-$GOFILE gen "Item=string,int"

هذا يخبرناgo generate، من خلال مساعدةgenny، لإنشاء نسخة مترجمةItemإلىstring، ونسخة ثانية للترجمةitemإلىint.

يركض

go generate

للحصول علىgen-set.goملف ، مع مجموعات سلسلة وكتف.

اختبارات

هام: التنفيذ العام لهيكل البيانات أعلاهيجمع ويمكن اختبارهابنفس سهولة التنفيذ الملموس الناتج عنgo generate، حتى نتمكن من إجراء اختبارات مقابل التنفيذ العام ، وكذلك الاختبارات الخاصة بالنوع.


المزيد من دروس Go: