Menu
Coddy logo textTech

יסודות Goroutines

חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 59 מתוך 107.

goroutine הוא תהליכון קל משקל המנוהל על ידי סביבת הריצה של Go. בניגוד לתהליכונים מסורתיים שצורכים כמות משמעותית של זיכרון, goroutine מתחיל עם כמה קילובייטים בלבד של שטח מחסנית, מה שמאפשר לך להריץ אלפים מהם במקביל.

כדי להתחיל goroutine, פשוט הציבו את מילת המפתח go לפני קריאה לפונקציה:

func sayHello(name string) {
    fmt.Println("Hello,", name)
}

func main() {
    go sayHello("Alice")  // פועל במקביל
    go sayHello("Bob")    // פועל במקביל
    
    time.Sleep(100 * time.Millisecond)
    fmt.Println("Done")
}

כאשר go sayHello("Alice") מתבצע, הוא לא ממתין עד ש־sayHello תסתיים. במקום זאת, הוא ממשיך מיד לשורה הבאה בזמן ש־sayHello פועלת ברקע. לכן אנחנו צריכים את time.Sleep; בלעדיו, main הייתה מסתיימת לפני שה־goroutines יושלמו.

אפשר גם להפעיל גורוטינות באמצעות פונקציות אנונימיות:

go func(msg string) {
    fmt.Println(msg)
}("Hello from goroutine")

הפונקציה הראשית עצמה רצה בתוך goroutine. כשהיא מסתיימת, כל שאר ה-goroutine מופסקות מיד. הן לא מקבלות הזדמנות לסיים. שימוש ב-time.Sleep הוא פתרון זמני; בשיעורים הבאים תלמדו טכניקות סנכרון מתאימות באמצעות ערוצים וקבוצות המתנה.

challenge icon

אתגר

קל

בואו נבנה מנהל משימות שמבצע כמה משימות במקביל באמצעות goroutines. תיצרו מערכת פשוטה שבה המשימות רצות ברקע בזמן שהתוכנית הראשית ממשיכה לפעול, וכך תדגימו כיצד goroutines מאפשרות ביצוע במקביל.

תארגנו את הקוד שלכם בשני קבצים:

  • tasks.go: הגדירו את לוגיקת ביצוע המשימות.

    צרו struct בשם Task עם השדות Name (מחרוזת) ו-Duration (מספר שלם, המייצג אלפיות שנייה).

    ממשו מתודה Run() עבור Task, שמדמה עבודה באמצעות השהיה למשך הזמן של המשימה, ואז מדפיסה: Task [Name] completed

    צרו פונקציה RunAllTasks(tasks []Task) שמפעילה את המתודה Run() של כל משימה כ-goroutine. לאחר הפעלת כל ה-goroutines, עליה להמתין 500 אלפיות שנייה כדי לאפשר להן להסתיים, ואז להדפיס: All tasks launched

  • main.go: קראו את פרטי המשימות ותזמרו את הביצוע במקביל.

    קראו את מספר המשימות, ואז קראו את השם ואת משך הזמן של כל משימה. צרו את המשימות והעבירו אותן אל RunAllTasks. לאחר שהיא תחזור, הדפיסו: Main function done

הקלטים הבאים יסופקו:

  • שורה 1: מספר המשימות (מספר שלם)
  • השורות הבאות: עבור כל משימה, שתי שורות — שם המשימה, ואז משך הזמן שלה באלפיות שנייה

לדוגמה, בהינתן:

3
Download
100
Process
50
Upload
75

הפלט שלכם צריך להציג את השלמת המשימות (הסדר עשוי להשתנות עקב הביצוע במקביל), ולאחר מכן את הודעות ההשלמה:

Task Process completed
Task Upload completed
Task Download completed
All tasks launched
Main function done

הערה: מכיוון ש-goroutines פועלות במקביל, משימות שמשך הזמן שלהן קצר יותר מסתיימות בדרך כלל ראשונות. סדר השלמת המשימות תלוי במשך הזמן שלהן — משימות קצרות יותר מסתיימות לפני משימות ארוכות יותר.

השתמשו ב-time.Sleep עם time.Duration ו-time.Millisecond עבור ההשהיות. זכרו שללא ההשהיה בתוך RunAllTasks, הפונקציה תחזור לפני שה-goroutines יסיימו את עבודתן.

נסו בעצמכם

package main

import (
	"fmt"
)

func main() {
	// קרא את מספר המשימות
	var numTasks int
	fmt.Scanln(&numTasks)

	// TODO: צור slice לשמירת המשימות
	
	// TODO: קרא את השם ומשך הזמן של כל משימה
	// עבור כל משימה:
	//   - קרא את שם המשימה
	//   - קרא את משך הזמן (כמספר שלם)
	//   - צור Task והוסף אותו ל-slice שלך

	// TODO: קרא ל-RunAllTasks עם ה-slice של המשימות שלך

	// TODO: הדפס "Main function done"
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Go אונליין