דילוג לתוכן המרכזי
מודול 7 · שיעור 2 מתוך 532/50 בקורס~15 min
שיעורי מודול (2/5)

ערוצים: תקשורת מודפסת

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

"אל תתקשר על ידי שיתוף זיכרון; שתף זיכרון על ידי תקשורת."

ערוץ הוא תור FIFO מוקלד, בטוח לסוג ובטוח עבור במקביל להשתמש. בשילוב עם go, זהו אבן הבניין העיקרית של Go במקביל.

ליצור, לשלוח, לקבל

Go
ch := make(chan int)     // canale di int, unbuffered

go func() {
    ch <- 42             // invia (può bloccare)
}()

v := <-ch                // ricevi (può bloccare)
fmt.Println(v)           // 42

תַחבִּיר:

  • make(chan T) או make(chan T, N) עבור מאוחסן.
  • ch <- v שולח.
  • v := <-ch מקבל.
  • v, ok := <-ch מקבל עם דגל (ok = false אם הערוץ סגור וריק).

לא מבוצר: מפגש

ערוץ לא מאגר (קיבולת 0) חוסם:

  • השולח עד שמקלט מוכן;
  • המקבל עד ששולח מוכן.

זה פגישה סינכרונית: שימושי כ"אות" או כדי להבטיח שהערך נמסר.

מאגר: תור עד N

Go
ch := make(chan int, 3)
ch <- 1   // non blocca
ch <- 2   // non blocca
ch <- 3   // non blocca
ch <- 4   // BLOCCA: il buffer è pieno

השולח חוסם רק כאשר המאגר מלא; המקלט בלבד כאשר הוא ריק.

קרוב ועבור טווח

השולח סוגר את הערוץ כשאין יותר ערכים:

Go
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)

for v := range ch {      // termina quando ch è chiuso E vuoto
    fmt.Println(v)
}

for range מעל ערוץ חוזר עד שהערוץ נסגר (ומתנקז). זהו הדפוס הנקי ביותר ל"צרוך כל מה שמגיע".

כיווניות בחתימות

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

Go
func producer(out chan<- int) {   // solo invio
    out <- 1
    close(out)
}

func consumer(in <-chan int) {    // solo ricezione
    for v := range in {
        fmt.Println(v)
    }
}

chan<- T = שליחה בלבד, <-chan T = קבלה בלבד. דו כיווני ניתן להעביר את הערוץ chan T לכל אחד מהם (המרה מרומזת). זה משפר את הבהירות ומונע טעויות.

תבניות נפוצות (תצוגה מקדימה)

  • בריכת עובדים: N גורוטינים צורכים מ-jobs <-chan T, מייצרים ב-results chan<- R.
  • צינור: שלבים המחוברים בערוצים.
  • אות סיום: ערוץ chan struct{} סגור כדי לאותת "עצור".
Go
done := make(chan struct{})
go func() {
    <-done    // blocca finché qualcuno chiude done
    cleanup()
}()
close(done)   // segnale di stop

chan struct{} הוא ערוץ ה"אות": אפס בתים של מטען, רק סנכרון.

נסה את זה

פעילות גופנית#go.m7.l2.e1
ניסיונות: 0טוען...

צור ערוץ int unbuffered ch, שלח 42 מ-goroutine, קבל ב-main והדפיס אותו.

טוען עורך...
הצג רמז

ללא חוצץ, השולח והמקלט מסתנכרנים.

הפתרון זמין לאחר 3 ניסיונות

פעילות גופנית#go.m7.l2.e2
ניסיונות: 0טוען...

שלח 1,2,3 על ערוץ מאוחסן, סגור אותו ואז הדפס הכל עם טווח טווח.

טוען עורך...
הצג רמז

'עבור טווח' מעל ערוץ מסתיים כאשר הערוץ סגור ומרוקן.

הפתרון זמין לאחר 3 ניסיונות

Quiz#go.m7.l2.e3
מוכן

מה עושה ערוץ UNBUFFERED כאשר השולח שולח אך אין מקלט מוכן?

Go
ch := make(chan int)
ch <- 1 // ?
אפשרויות תשובה

לְסַכֵּם

  • ערוץ = תור FIFO מודפס, בטוח בין גורוטיינים.
  • Unbuffered: מפגש (שולח ומקבל מסתנכרנים).
  • מוצץ: ניתוק, חוסם רק כאשר הוא מלא/ריק.
  • close(ch): רק השולח; for range צורכת עד לסגירה.
  • כיווניות: chan<- T (לשליחה בלבד), <-chan T (לקבלה בלבד).
  • chan struct{} כערוץ אות לסנכרון טהור.