@nigun אמר בהאזנה לערוץ בתוך כמה פונקציות במקביל:
האם אני עובד נכון או לא?
אני מאמין שככל שתסביר יותר את הסיטואציה יגדלו הסיכויים שתהיה לך תשובה מדוייקת יותר. (סיטואציה, לא צרכים נגזרים מהסיטואציה)
@nigun אמר בהאזנה לערוץ בתוך כמה פונקציות במקביל:
האם אני עובד נכון או לא?
אני מאמין שככל שתסביר יותר את הסיטואציה יגדלו הסיכויים שתהיה לך תשובה מדוייקת יותר. (סיטואציה, לא צרכים נגזרים מהסיטואציה)
@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)
}
@nigun לכאורה אתה צודק, אם זה המצב אז הקוד כבר מרגיש לי מידי מסטיקי, אולי תשקול לעבוד עם קולבקים פרימיטייבים? או לחילופין לממש את הרעיון של סגירת ערוץ שתשלח הודעה לכולם, ואת הערך שאתה רוצה להעביר תעביר עם איזה משתנה גלובלי?
@nigun אמר בהאזנה לערוץ בתוך כמה פונקציות במקביל:
לבניים אני מוותר על סגירת הערוץ, ורק מוחק אותו מהמערך
השאלה היא מה ההשלכות?
לפי מה שכתוב פה
https://stackoverflow.com/questions/8593645/is-it-ok-to-leave-a-channel-open
אין צורך לסגור את הערוץ, מספיק לנקות את המצביע אליו ואיסוף הזבל ידאג לשאר
@dovid אם כל מופע לפני שהוא נמחק הוא קורא למתודה Dispose של עצמו, וכשהמופע של הקונטרולר מתנקה כל הנכסים שלו גם נמחקים, אז גם המופע של הקונטקסט נמחק, למה שהמתודה Dispose של הקונטקסט לא תקרא לבד? למה אני צריך לקרוא לה?
@nigun טעיתי, בקוד הזה באמת שליחת המידע מתבצעת רק אחרי שכל המאזינים נרשמים, אם נעשה את זה כך:
https://play.golang.org/p/hjKVDAq2hLT
לא נראה את המידע השני, אבל זה לא בגלל שאי אפשר להוסיף איברים למערך, אלא בגלל שבזמן שאמור להישלח המידע הקומפיילר עדיין באמצע השינה, וכשהוא מתעורר מהשינה כבר מאוחר כי הפונקציה main כבר מתה.
ניסיתי לעשות את זה עם שרת HTTP וזה נראה עובד בסדר גמור
package main
import (
"fmt"
"net/http"
)
var (
mainChan = make(chan string)
channels = []chan string{}
)
func main() {
go func() {
for {
msg := <-mainChan
for _, c := range channels {
c <- msg
}
}
}()
http.HandleFunc("/a", sendDataToChannel)
http.HandleFunc("/b", someThread)
http.ListenAndServe(":8090", nil)
}
func sendDataToChannel(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "")
mainChan <- "foo"
}
func someThread(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "")
go func() {
c := addListener()
// for {
s := <-c
fmt.Println(s)
// }
}()
}
func addListener() chan string {
newChan := make(chan string)
channels = append(channels, newChan)
return newChan
}
@nigun הקוד הזה עובד מצוין
https://play.golang.org/p/YOYhQerLKFd
כמובן שאחרי המידע הראשון שנשלח לערוץ המאזין נסגר ואי אפשר לשלוח עוד מידע, אבל המידע הראשון מתקבל גם לפונקציות המאוחרות.
הקוד שהעלת קטוע, אולי תעלה דוגמת קוד שלימה עם בעיה
@MusiCode הכלל אומר לא לשים את הוראות העיצוב עצמם בתוך התגיות, אבל אם לא תשים קלאסים איך תעצב אותם ב CSS?
@nigun הקוד שהבאתי הוא בסיס מופשט להבנת הענין
package main
import (
"fmt"
"time"
)
var (
// הערוץ הראשי שאליו מוזרם המידע
mainChan = make(chan string)
// מערך של ערוצי משנה
// כל פונקציה שתרצה לקבל מידע מהערוץ הראשי תצטרך ליצור ערוץ משנה ולהוסיף אותו למערך הזה
channels = []chan string{}
)
func main() {
go func() {
// פונקציה היחידה שמקבל את המידע מהערוץ הראשי ומזרימה אותו לערוצי המשנה
msg := <-mainChan
for _, c := range channels {
c <- msg
}
}()
go func(c chan string) {
time.Sleep(2 * time.Second)
c <- "foo"
}(mainChan)
go someThread()
go someThread()
go someThread()
go someThread()
time.Sleep(4 * time.Second)
}
func someThread() {
c := addListener()
s := <-c
fmt.Println(s)
}
func addListener() chan string {
// הפונקציה שתפקידה ליצור את ערוצי המשנה ולהוסיף אותם למערך כדי להאזין למידע מהערוץ הראשי
newChan := make(chan string)
channels = append(channels, newChan)
return newChan
}
זה עובד טוב בשביל פונקציות חד פעמיות, אם תרצה להפוך את זה למאזינים רב פעמיים, לא צריך לעשות הרבה, רק להוסיף לולאות אינסופיות שמאזינות למידע מהערוץ, כך שברגע שיתקבל מידע מהערוץ הפונקציה תעשה את המוטל עליה ומיד אחר כך תמשיך לאיטרציה הבאה בלולאה ששוב מאזינה לערוץ:
package main
import (
"fmt"
"time"
)
var (
mainChan = make(chan string)
channels = []chan string{}
)
func main() {
go func() {
for { // << לולאה אינסופית שמאזינה לערוץ הראשי
msg := <-mainChan
for _, c := range channels {
c <- msg
}
}
}()
go func(c chan string) {
time.Sleep(1 * time.Second)
c <- "foo"
time.Sleep(1 * time.Second)
c <- "foo" // << שליחת מידע לערוץ הראשי פעם נוספת
}(mainChan)
go someThread()
go someThread()
go someThread()
go someThread()
time.Sleep(4 * time.Second)
}
func someThread() {
c := addListener()
for { // << לולאה אינסופית שמאזינה לערוץ המשנה
s := <-c
fmt.Println(s)
}
}
func addListener() chan string {
newChan := make(chan string)
channels = append(channels, newChan)
return newChan
}
עד כאן הכל פשוט, הבעיה מתחילה בסיטואציה של השואל בסטאק, שיתכנו מאזינים שנרשמו לערוצי המשנה, ובהמשך הם יתנתקו וירדו מההאזנה, הבעיה היא שכל מאזין מריץ לולאה אינסופית, ואם לא תעצור את הלולאה כשהוא יתנתק זה יגרום לשימוש מיותר בזיכרון. בשביל זה הוא צריך להוסיף לכל מאזין גם תנאי עצירה, ולכן הוא הוסיף את הערוץ quit, וזה סיבך את הקוד.
האם אתה גם צריך את זה? זה תלוי באופי השימוש של המאזינים שאתה מקים, אם הם אמורים לרוץ כל חיי האפליקציה, אז זה מיותר, אם יש סיכוי שחלק מהם או כולם יגמרו את התפקיד שלהם וימותו, אז תצטרך לדאוג לעצירת הלולאה.
גם למקרה שצריך לעצור את הלולאה, אם המקרה של סיום התפקיד של הפונקציה ידוע וצפוי מראש, לא תצטרך להשתמש בשיטה של הערוץ quit, אלא פשוט תעצור את הלולאה בעצמך, אם זה לא תלוי בידך אלא זה מקרה לא צפוי (כמו במקרה של השואל שם שמשתמש יתנתק) לזה נועד השימוש בערוץ וב select
בעיה נוספת שהעלו שם, אם המאזינים נרשמים ומתווספים למערך בו בזמן שהערוץ בפעולה, והפתרון שהוא הציע זה לנעול את הערוץ עם sync.Mutex בזמן שמוסיפים מאזין ולשחרר אותו אחר כך, אבל לא הצלחתי להבין מה בדיוק יגרום לבעיה ולמה צריך את הפיתרון.
@nigun יתכן שהמקרה שלך שונה מהמקרה של השואל בסטאק, הוא היה צריך לשלוח כמה פעמים מידע לאותו ערוץ, מהדוגמת קוד שלך נראה שכל המאזינים הם חד פעמיים, אם זה המצב, אתה יכול להסתפק במערך שמחזיק את כל המאזינים, וכשהערוץ הראשי שולח מידע אתה עובר בלולאה על המערך ומעביר את המידע לכלל המאזינים.
https://play.golang.org/p/-ynOQTKzXMu
@יוס אני לא בטוח שהבנתי אותך, יש את הדומיין שהדפדפן טוען, זה שכתוב בדפדפן ככתובת האתר, זה האתר הראשי, נקרא לו דומיין X
כעת הדפדפן שפתח את האתר של דומיין X, שולח בקשת AJAX לדומיין Y
זו המציאות?
@יוס אמר בשגיאה ב API מול וורדפרס:
הוספתי גם את זה ועדיין לא נפתר
איפה הוספת את זה? זה צריך להיות בדומיין השני, אם אתה פונה בבקשה מדומיין X לדומיין Y, דומיין Y צריך להוסיף את הכותרות האלה לתשובה
בלי ניסיון, תבדוק אם זה מתאים לך
https://sailsjs.com/
ואולי תעבור גם על הרשימה פה
https://www.ubuntupit.com/best-nodejs-cms-platforms/
אם אחת מהם מתאימה
@avr416 דברים כדורבנות, אבל המציאות לא תמיד מסכימה עם הפילוסופיה הזו, על עצמי אני יודע שאם הייתי מנסה לעבוד כך הייתי היום תקוע איפשהו בהבנת המושג מערך, דוקא כשנתקלתי בבאגים שאתה מתאר הוכרחתי להבין את הדברים יותר לעומק, ועד היום אני מבין יותר דברים בזכות באגים
scaleway חוסמים בברירת מחדל, ואפשר לבקש מהם לפתוח את הפורט, לא יודע לפי איזה קריטריונים הם פותחים, אבל ביקשתי פעמיים ולא סורבתי
@smk123 תתחיל, גש למערכת קבצים, תקרא את רשימת הקבצים שבתיקית המקור ותטען אותם למערך, ואז תחלק את המערך לפרוסות של מערכים קטנים של 4 קבצים, תעבור בלולאה על המערך הראשי ותעתיק את הקבצים שבתתי המערכים לתיקיות משנה, ותקרא להם בשמות שאתה רוצה. עד כאן בסדר?
@smk123 איזו שפה אתה מכיר?
@smk123 מה מיוחד ב BAT? כתוב את זה בכל שפה שאתה מכיר
@avr416 אמר בחיפוש מתוך שדה חופשי:
זה לא איזה פונקציה קיימת, וזה חתיכת פרוייקט מורכב.
לכאורה הפול טקסט עונה על הצרכים האלה, אבל אני לא יודע מה רמת התמיכה שלו בעברית
@אבי-203 אולי full text search יעזור