دروس الوحدة (4/5)
عمليات الإغلاق والوظائف كقيم
في Go، الوظائف هي قيم من الدرجة الأولى: يمكن إسنادها إليها المتغيرات، وتمريرها إلى وظائف أخرى، وإعادتها. الإغلاق هو وظيفة حرفية (مجهولة) ** تلتقط ** متغيرات ملف البيئة التي يتم تعريفها.
دالة حرفية
دالة بدون اسم، مكتوبة في السطر. اتصل به على الفور أو تعيينه:
greet := func(name string) {
fmt.Println("ciao", name)
}
greet("Anna")
// invocata immediatamente:
func() { fmt.Println("subito") }()نوع greet هو func(string).
الاستيلاء على البيئة: الإغلاق
يمكن للوظيفة الحرفية قراءة وتعديل المتغيرات المرئية فيها نطاقه المعجمي، حتى بعد عودة الوظيفة الخارجية:
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
fmt.Println(c(), c(), c()) // 1 2 3n "يعيش" طالما أن إغلاقًا واحدًا على الأقل يشير إليه. كل دعوة ل
يقوم counter() بإنشاء n جديد ومستقل.
الإغلاق كرد اتصال
نمط شائع جدًا:
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})يلتقط الإغلاق nums ويحدد الترتيب.
وظائف كمعلمات
لقبول دالة كمعلمة، اكتب نوعها:
func apply(nums []int, f func(int) int) []int {
out := make([]int, len(nums))
for i, n := range nums {
out[i] = f(n)
}
return out
}
double := func(x int) int { return x * 2 }
apply([]int{1, 2, 3}, double) // [2 4 6]إذا أصبح من الصعب قراءة التوقيع، فحدد اسم مستعار للنوع:
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }جربه
تحديد العداد () الذي يُرجع الإغلاق: كل استدعاء للإغلاق يزيد ويعيد عدادًا داخليًا.
إظهار التلميح
يجب الإعلان عن `n` قبل الإرجاع؛ الإغلاق يلتقطها.
الحل متاح بعد 3 من المحاولات
قم بتعيين دالة حرفية إلى f تطبع "ciao"، ثم اتصل بها.
إظهار التلميح
بناء الجملة: `f := func() { ... }` ثم `f()`.
الحل متاح بعد 3 من المحاولات
ماذا يطبع هذا؟ (احترس من نطاق الإغلاق)
mk := func() func() int {
x := 0
return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())خلاصة
- الوظائف من الدرجة الأولى: قابلة للإحالة، ومقبولة، وقابلة للإرجاع.
- الوظيفة الحرفية:
func(params) ret { ... }، مجهول. - الإغلاق: يلتقط متغيرات النطاق المعجمي، ويبقيها حية.
- نوع الوظيفة الصريحة في المعلمات:
func(int) int. - منذ Go 1.22، كل تكرار له نسخته الخاصة من متغير الحلقة.