שיעורי מודול (2/5)
ערוצים: תקשורת מודפסת
ערוצים הם המנגנון האידיומטי לתקשורת ביניהם גורוטינים. פילוסופיית הגו (רוב פייק):
"אל תתקשר על ידי שיתוף זיכרון; שתף זיכרון על ידי תקשורת."
ערוץ הוא תור FIFO מוקלד, בטוח לסוג ובטוח עבור במקביל
להשתמש. בשילוב עם 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
ch := make(chan int, 3)
ch <- 1 // non blocca
ch <- 2 // non blocca
ch <- 3 // non blocca
ch <- 4 // BLOCCA: il buffer è pienoהשולח חוסם רק כאשר המאגר מלא; המקלט בלבד כאשר הוא ריק.
קרוב ועבור טווח
השולח סוגר את הערוץ כשאין יותר ערכים:
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 מעל ערוץ חוזר עד שהערוץ נסגר (ומתנקז).
זהו הדפוס הנקי ביותר ל"צרוך כל מה שמגיע".
כיווניות בחתימות
פרמטרי פונקציה יכולים להגביל את הכיוון:
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{}סגור כדי לאותת "עצור".
done := make(chan struct{})
go func() {
<-done // blocca finché qualcuno chiude done
cleanup()
}()
close(done) // segnale di stopchan struct{} הוא ערוץ ה"אות": אפס בתים של מטען, רק
סנכרון.
נסה את זה
צור ערוץ int unbuffered ch, שלח 42 מ-goroutine, קבל ב-main והדפיס אותו.
הצג רמז
ללא חוצץ, השולח והמקלט מסתנכרנים.
הפתרון זמין לאחר 3 ניסיונות
שלח 1,2,3 על ערוץ מאוחסן, סגור אותו ואז הדפס הכל עם טווח טווח.
הצג רמז
'עבור טווח' מעל ערוץ מסתיים כאשר הערוץ סגור ומרוקן.
הפתרון זמין לאחר 3 ניסיונות
מה עושה ערוץ UNBUFFERED כאשר השולח שולח אך אין מקלט מוכן?
ch := make(chan int)
ch <- 1 // ?לְסַכֵּם
- ערוץ = תור FIFO מודפס, בטוח בין גורוטיינים.
- Unbuffered: מפגש (שולח ומקבל מסתנכרנים).
- מוצץ: ניתוק, חוסם רק כאשר הוא מלא/ריק.
close(ch): רק השולח;for rangeצורכת עד לסגירה.- כיווניות:
chan<- T(לשליחה בלבד),<-chan T(לקבלה בלבד). chan struct{}כערוץ אות לסנכרון טהור.