דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. האזנה לערוץ בתוך כמה פונקציות במקביל

האזנה לערוץ בתוך כמה פונקציות במקביל

מתוזמן נעוץ נעול הועבר תכנות
25 פוסטים 3 כותבים 485 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • nigunN מנותק
    nigunN מנותק
    nigun
    השיב ליוסף בן שמעון ב נערך לאחרונה על ידי nigun
    #13

    @יוסף-בן-שמעון
    מצאתי את הפתרון😁 😂 :smile: 🔓 😌 🤸
    פשוט הערוצים הישנים מתו כבר לא מאזינים,אבל עדיין נמצאים במערך
    וכיוון שהם הראשונים במערך, הלולאה מחכה לשדר למאזין הראשון במערך ולא ממשיכה הלאה.
    הפתרון הוא להסיר את הערוץ מהמערך אחרי שהוא מפסיק להאזין

    func someThread(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "")
            go func() {
                    c := addListener()
                    s := <-c
                    fmt.Println(s)
    //קודם כל אני סוגר את הערוץ (לא בטוח שזה חכם)
                    close(c)
    // אני מריץ ללואה שמסירה את הערוץ המת מהמערך
                    for i := 0; i < len(channels); i++ {
                            chanvar := channels[i]
                            if chanvar == c {
                                    channels = append(channels[:i], channels[i+1:]...)
                                    i-- // Important: decrease index
                                    break
                            }
    
                    }
            }()
    }
    
    

    השאלה היא מה יקרה אם יגיע קריאה חדשה לערוץ הראשי תוך כדי שאני סוגר את הערוץ לפני שאני מסיר אותו מהמערך
    לכאורה אני יקבל שגיאה

    panic: send on closed channel
    
    

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

    מייל: nigun@duck.com

    י 2 תגובות תגובה אחרונה
    1
    • י מנותק
      י מנותק
      יוסף בן שמעון
      השיב לnigun ב נערך לאחרונה על ידי
      #14

      @nigun אמר בהאזנה לערוץ בתוך כמה פונקציות במקביל:

      לבניים אני מוותר על סגירת הערוץ, ורק מוחק אותו מהמערך
      השאלה היא מה ההשלכות?

      לפי מה שכתוב פה
      https://stackoverflow.com/questions/8593645/is-it-ok-to-leave-a-channel-open
      אין צורך לסגור את הערוץ, מספיק לנקות את המצביע אליו ואיסוף הזבל ידאג לשאר

      תגובה 1 תגובה אחרונה
      1
      • י מנותק
        י מנותק
        יוסף בן שמעון
        השיב לnigun ב נערך לאחרונה על ידי
        #15

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

        nigunN תגובה 1 תגובה אחרונה
        1
        • nigunN מנותק
          nigunN מנותק
          nigun
          השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
          #16

          @יוסף-בן-שמעון
          איך אני יאזין למשתנה בין הערוצים? עם האזנה אינסופית עם if ובמקרה שהמשתנה שונה מהקריאה הקודמת לעשות פעולה כל שהיא?

          מייל: nigun@duck.com

          י תגובה 1 תגובה אחרונה
          0
          • י מנותק
            י מנותק
            יוסף בן שמעון
            השיב לnigun ב נערך לאחרונה על ידי
            #17

            @nigun אני מדבר על משהו כזה

            package main
            
            import (
            	"fmt"
            	"time"
            )
            
            var data string
            
            func main() {
            	c := make(chan string)
            
            	go func(c chan string) {
            		time.Sleep(2 * time.Second)
            		data = "foo"
            		close(c)
            
            	}(c)
            
            	go func() {
            		<-c
            		fmt.Println(data)
            
            	}()
            	go func() {
            		<-c
            		fmt.Println(data)
            
            	}()
            
            	time.Sleep(4 * time.Second)
            }
            
            
            nigunN תגובה 1 תגובה אחרונה
            0
            • nigunN מנותק
              nigunN מנותק
              nigun
              השיב ליוסף בן שמעון ב נערך לאחרונה על ידי nigun
              #18

              @יוסף-בן-שמעון
              אני צריך שליחה רב פעמית
              זאת אומרת שאני יוסיף ויוריד מאזינים (שיוכלו להאזין פעם אחת או יותר)
              ולשלוח כל הזמן (עם שרת HTTP ) מידע שיעבור לכל המאזינים
              את האמת אני צריך לשלוח את המידע לרוב רק למאזין אחד, (כי כל מאזין שייך למשתמש אחר)
              ואני שולח את הבקשה בצורה כזאת USER:DATA ולמאזין אני בונה לולאה שמאזינה כל הזמן לערוץ
              ואם היוזר שווה ליוזר שלו הוא עושה את הפעולה המבוקשת ואם לא הוא חוזר להאזין,
              האם אני עובד נכון או לא?

              מייל: nigun@duck.com

              י תגובה 1 תגובה אחרונה
              0
              • י מנותק
                י מנותק
                יוסף בן שמעון
                השיב לnigun ב נערך לאחרונה על ידי
                #19

                @nigun אמר בהאזנה לערוץ בתוך כמה פונקציות במקביל:

                האם אני עובד נכון או לא?

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

                nigunN תגובה 1 תגובה אחרונה
                0
                • nigunN מנותק
                  nigunN מנותק
                  nigun
                  השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
                  #20

                  @יוסף-בן-שמעון
                  אני לרוב מסתבך כשכותבים מידי הרבה פרטים, אבל אם זה יעזור אז מצויין.
                  אני בונה מרכזיה באסטריסק שבו אני רוצה לשלוט על חלק מהמאזינים
                  דהיינו לדחוף להם באמצע האזנה פקודות שונות דרך API משרת HTTP
                  (אמנם יש לאסטריסק API לשליחת פקודות כאלו ,אבל אני לא הצלחתי להשתמש בו למה שאני צריך)
                  לכן חשבתי ללכת על הכיוון של ערוצי GO שפשוט כל שיחה (שאני רוצה לשלוט עליה) תאזין לערוץ
                  ובAPI החיצוני אני ישלח את שם המאזין שבו אני רוצה לשלוט , ואת הפקודה שאני רוצה שהוא יבצע
                  כשמתקבל בקשה כל המאזינים יבצעו בדיקה האם הבקשה מופנית אליהם, ואם כן יבצעו אותה
                  לקינוח אני יכול להחזיר באותה צורה הודעה דרך ערוץ אחר לשרת HTTP שהפעולה התבצעה +מידע על התוצאה.

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

                  מייל: nigun@duck.com

                  י תגובה 1 תגובה אחרונה
                  0
                  • י מנותק
                    י מנותק
                    יוסף בן שמעון
                    השיב לnigun ב נערך לאחרונה על ידי
                    #21

                    @nigun סורי, לא הצלחתי להבין איך נכנסו הערוצים לתמונה, למה לא לעשות כמו שעשו כל הדורות מימות אסמבלי ועד ימינו, כשמגיע השלב שאתה רוצה לדחוף פקודה למאזין, קרא לפונקציה חיצונית, תעביר לה פרמטרים נצרכים (user, data) ותקבל את הערך המוחזר. (אולי בגלל שאני לא מכיר אסטריסק)

                    nigunN תגובה 1 תגובה אחרונה
                    0
                    • nigunN מנותק
                      nigunN מנותק
                      nigun
                      השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
                      #22

                      @יוסף-בן-שמעון
                      פשוט אין שלב שבו אני רוצה לקרוא למאזין
                      אני תמיד רוצה להשאיר את האופציה לקריאה פתוחה
                      למשל אם המאזין הרגע התחיל להקשיב לקובץ באורך של שעה, ואני רוצה להעיף אותו משם ,שיקשיב למשהו אחר
                      אני פשוט בונה את כל הפקודות בצורה אסינכרונית , דהיינו שמפעיל את הפקודה "השמע קובץ פלוני" אבל עם go לפני הפקודה
                      ומיד אחר כך ממשיך להמתין לפקודות שלי
                      ככה זה נראה בערך בקוד

                      
                       for {
                                           	msg := <-c
                                              msgsplit := strings.Split(mesege, ":")
                                              if msgsplit[0] == user {
                      
                                                      filename := msgsplit[1]
                                                 
                                                      go myAgi.StreamFile(filename, "")
                                                    
                      
                                              }
                      
                      

                      בקוד הנ"ל המאזין מקבל את הערך מהערוץ בודק האם זה תואם את השם שלו
                      אם כן , הוא בודק מה הערך השני שנשלח (אחרי הנקודותיים)
                      ומשמיע את הקובתץ למאזין ומיד אחרי הפקודה להשמיע את הקובץ הוא חוזר להאזין.

                      מייל: nigun@duck.com

                      י תגובה 1 תגובה אחרונה
                      0
                      • י מנותק
                        י מנותק
                        יוסף בן שמעון
                        השיב לnigun ב נערך לאחרונה על ידי
                        #23

                        @nigun מה דעתך על שימוש במפה, שהמפתחות שלה הם המזהים של המשתמשים, נראה לי יותר קריא ונקי
                        כל משתמש שמתחבר אתה מקים לו ערוץ, וכשהוא יתנתק אתה דואג לנתק אותו כדי לשחרר את הערוץ ולעצור את ההאזנה האינסופית

                        package main
                        
                        import (
                        	"fmt"
                        	"time"
                        )
                        
                        var usersChannels = make(map[string]chan string)
                        
                        func main() {
                        	go helloUser("A")
                        	go helloUser("B")
                        	time.Sleep(500)
                        	sendDataToUser("A", "Hi")
                        	sendDataToUser("B", "By")
                        	time.Sleep(500)
                        	disconnectUser("A")
                        	sendDataToUser("A", "Hi")
                        	time.Sleep(5000)
                        }
                        
                        func helloUser(name string) {
                        	usersChannels[name] = make(chan string) // כאן אתה מוסיף את הערוץ של המשתמש למפה
                        	for {
                        		msg, isConnected := <-usersChannels[name] // מאזין למידע מהערוץ
                        		if !isConnected { // אם המידע הוא שהערוץ נסגר, זה אומר שהמשתמש התנתק ואפשר לעצור את הפונקציה
                        			return
                        		}
                        		fmt.Println(msg)
                        	}
                        }
                        
                        func disconnectUser(name string) { // סוגר את הערוץ כדי לעצור את ההאזנה ומוחק את המשתמש מהמפה
                        	close(usersChannels[name])
                        	delete(usersChannels, name)
                        }
                        
                        func sendDataToUser(name, data string) {
                        	channel, hasUser := usersChannels[name]
                        	if hasUser { // כדי למנוע מצב שהמשתמש כבר התנתק והערוץ שלו לא קיים במפה
                        		channel <- data
                        	}
                        }
                        
                        
                        תגובה 1 תגובה אחרונה
                        2
                        • י מנותק
                          י מנותק
                          יוסף בן שמעון
                          כתב ב נערך לאחרונה על ידי
                          #24

                          @nigun אליבא דאמת שימוש בערוצים במקרה הזה סתם מכביד על הקוד, קח מוטציה קלילה יותר של זה, במקום ערוצים שמתי קולבקים

                          package main
                          
                          import (
                          	"fmt"
                          	"time"
                          )
                          
                          var usersCallback = make(map[string]func(data string))
                          
                          func main() {
                          	go helloUser("A")
                          	go helloUser("B")
                          	time.Sleep(500)
                          	sendDataToUser("A", "Hi")
                          	sendDataToUser("B", "By")
                          	time.Sleep(500)
                          	disconnectUser("A")
                          	sendDataToUser("A", "Hi")
                          	time.Sleep(5000)
                          }
                          
                          func helloUser(name string) {
                          	usersCallback[name] = func(msg string) {
                          		fmt.Println(msg)
                          	}
                          }
                          
                          func disconnectUser(name string) {
                          	delete(usersCallback, name)
                          }
                          
                          func sendDataToUser(name, data string) {
                          	callback, hasUser := usersCallback[name]
                          	if hasUser {
                          		callback(data)
                          	}
                          }
                          
                          
                          nigunN תגובה 1 תגובה אחרונה
                          1
                          • nigunN מנותק
                            nigunN מנותק
                            nigun
                            השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
                            #25

                            @יוסף-בן-שמעון
                            את האמת אני לא מכיר בכלל את הקונספט של קולבקים
                            כנראה אני אשב על זה מתי שהוא ללמוד את זה (לא נראה מסובך)

                            מייל: nigun@duck.com

                            תגובה 1 תגובה אחרונה
                            0

                            • 1
                            • 2
                            בא תתחבר לדף היומי!
                            • התחברות

                            • אין לך חשבון עדיין? הרשמה

                            • התחברו או הירשמו כדי לחפש.
                            • פוסט ראשון
                              פוסט אחרון
                            0
                            • דף הבית
                            • קטגוריות
                            • פוסטים אחרונים
                            • משתמשים
                            • חיפוש
                            • חוקי הפורום