מדריך: כתיבת אפליקציות בGO
-
בהמשך לפוסט הזה אני מנסה להתחיל לכתוב מדריך מקיף לGO
אני לא יודע כמה זמן אני ישרוד וכמה זה יצא מדריך מקצועי? אבל ננסה.קודם כל קצת היסטוריה
שפת GO התחילה בשנת 2007, ע"י מפתחי C++ שעבדו בגוגל, והיו מתוסכלים מכמה דברים בשפה:
1.זמן קיפול ארוך (כ45 דקות בפרוייקט שהם עבדו עליו).
2.חוסר תמיכה מספיקה בתכנות אסינכרוני (לא נראה לי שאני צריך להסביר כאן מה זה קוד אסינכרוני).הם התחילו לעבוד (במימון של גוגל) על שפה חדשה
עם המאפיינים הבאים :
1.קוד שיקומפל לשפת מכונה (ולא ירוץ ע"י מפרש כמו PHP,פייתון וכו').
2.קוד קריא ונוח לעבודה בעבודות צוות.
3.תמיכה בקוד אסינכרוני בעלות נמוכה, ושהקוד ישאר קריא.
4.קימפול מהיר.
5.הם בנו את האיסוף זבל ואת הruntime בצורה שונה מC, אבל אני עדיין לא הבנתי מה הקטע שם (אבל בכל מקרה זה לא משנה למתכנת ברוב המקרים)הם שיחררו את הפרוייקט באיזור 2009, ובאיטיות זה התחיל לתפוס (בעיקר כי גוגל דחפו את זה )
אבל מה שכנראה הקפיץ את השפה זה דוקר, כשהמנהלים של דוקר חיפשו ב2012 איזה שפה מתאימה לפרוייקט שלהם
הם בחרו בGO אפילו שזה עדיין היה חדש, כי הם חיפשו דווקא שפה חדשה שקל לכתוב בה בצוות ענק בקוד פתוח, ושהיה קוד אסינכרוני קל לניהול, וגם בגלל שהם ראו שאם הם יבחרו שפה ישנה הם יפספסו תמיכה מכל אלו שכותבים בשפה המתחרה
למעשה זה הביא הרבה אנשים להכיר את השפה ולכן היא GO התחילה להיות חזק בשוק מ2015 בערך .השפה נועדה לשמש בעיקר בצד שרת ( קונטיינרים, כלי CLI,מסדי נתונים, API)
ובשביל צד לקוח אפשר להשתמש או בתבניות HTML של GO או בריאקט, אנגולר וכדו'.(מעניין שהיום מנסים למשוך את GO לעוד כיוונים כמו:
tinygo משיועד לחומרה קטנה כמו ארדואינו,
gopherjs שמקפל GO לJS (לא ברור מה הקטע בזה אבל זה נושא לשיחה אחרת),
fyne לבניית אפלקציות לשולחן עבודה (ללא תלות באלקטרון וכו'),
יהיה מעניין לראות האם אכן זה אכן יעבור לתחומים נוספים.)יש כמה קשיים לאלו שמגיעים משפות יותר גבוהות
1.הקומפיילר מחמיר מאוד ולא נותן לקפמל אם יש משתנים שלא בשימוש, וזה יכול הציק בהתחלה, אבל בסופו של יום מרויחים קוד נקי.
2.כמו שאר השפות ה"נמוכות" צריך להגדיר מראש את הסוג של כל משתנה , וכדי להשתמש בו אחר כך כסוג אחר, צריך המרה.
(אני לא יודע בדיוק למה בשפות נמוכות זה עובד ככה, האם בגלל ביצועים או בגלל שטכנית הקומפיילר חייב לדעת מראש מה הסוג של המשתנה?) -
התקנת סביבת עבודה
להתקנה בווינודס אפשר לחפש את ההוראות התקנה כאן
בלינוקס הכי פשוט להשתמש בסקריפט הבאwget -q -O - https://raw.githubusercontent.com/canha/golang-tools-install-script/master/goinstall.sh | bash
ולפעול לפי ההוראות
אפשר לבדוק האם זה הותקן בהצלחה עםgo version
הסקריפט הנ"ל מתקין את GO ויוצר את התיקייה GO (ששם נבנה את כל האפליקציות שלנו) בתיקיית המשתמש.
תחת התיקייה GO יש 3 תיקיות:
src - התיקייה בו אתם תשמרו את כל הקוד שלכם.
pkg - התיקייה מתחתיה נמצאים קבצים מקומפלים וכן החבילות הרלוונטיות למערכת הפעלה שלכם (GO מתקפל בקלות לכל מערכות ההפעלה בלי צורך בשינוי בקוד, אבל כיוון שיש API אחר לכל מערכת הפעלה צריך את החבילות האלו, אבל לא נראה לי שיש למשתמש הפשוט משהו לשנות שם) אם מישהו יכול להסביר יותר מה קורה בתיקיה הזאת נשמח לשמוע .
bin - התיקייה אליה נשלחים הקבצים המקופלים (אפליקציה אותה ניתן להריץ בפועל).נ.ב. למי שרוצה לשחק קצת עם הקוד בלי להתקין אפשר להתנסות כאן
-
שלום עולם
עכשיו ניצור תיקיה חדשה תחת src בשם hello
ובתוכו ניצור קובץ בשם main.gopackage main import "fmt" func main() { fmt.Printf("hello, world\n") }
ונריץ את הקובץ עם הפקודה
go run $HOME/go/src/hello/main.go
(הפקודה go run בעצם מקמפלת את האפליקציה שלנו לספרייה זמנית, ומריצה אותה משם)
עכשיו ננסה לעבור על כל קטע ולהסביר מה קורה
נתחיל דווקא מהסוףfunc main() { fmt.Printf("hello, world\n") }
קודם כל הקדמה קצרה
GO היא שפת תכנות פונקציונלית
שזה בעצם אומר שכל הקוד נכתב רק בתוך פונקציות
האפליקציה תמיד מריצה רק את פונקציית main,
ובתוכו אנו יכולים לקרוא לכל שאר הפונקציות שלנו
(ואם יש פונקציה שלא קוראים לה הקומפיילר פשוט מתעלם ממנה).
אז בקוד שלנו אנו רואים שיש פונקציה בשם main (הכרזה על פונקציה נעשית עם המילהfunc
)
ובתוכו אנו קוראים לפונקציה בשםfmt.Printf
, עם הערךhello, world\n
.
בשביל להבין מאיפה בפונקציה השאת צצה אנו נחזור עכשיו לתחילת הקוד שלנוpackage main import "fmt"
כאן אנחנו קראנו לחבילה שלנו main
ואחר כך ייבאנו את החבילה fmt (זה דומה לrequire בPHP)
(החבילה fmt היא חבילת ברירת מחדל של GO לטיפול בסטרינגים )
ובתוכו יש פונקציה בשם Printf שמדפיסה את הערך שהועבר אליה
ניתן לראות את הפונקציה בnano $HOME/.go/src/fmt/print.go
שם אנו יכולים לראות ששם החבילה היא fmt
ובתוכו יש פונקציה קצת מסובכת שבסופו של יום מדפיסה את הערך המבוקשאז בחזרה לקוד שלנו
fmt.Printf("hello, world\n")
קורא לפונקציה Printf שנמצאת בתוך חבילת fmt
(אם הייתי מעתיק את כל התיקייה של fmt לתקייה של הקוד שלנו הייתי קורא לפונקציה אותו דבר
אבל לא הייתי צריך לעשות import,
בקיצור import זה כמו להעתיק את התקייה המבוקשת לתקייה שלנו,
מצד שני אם היה בתקייה של fmt קובץ עם החבילה main הייתי קורא לה ישירות בלי כותרת לפני (כך אני מבין את זה אף פעם לא ניסיתי בפועל).
אפשר להרחיב על זה עוד אבל כיוון שאנחנו לא כותבים חבילות גדולות אז ה לא רלוונטי כרגע) -
תכנות אסינכרוני בGO
בGO ניתן לקרוא לפונקציה ולא לחכות עד היא תגמר על ידי נוספת המילה go לפני הפונקציה
בא נקח קוד לדוגמא (אפשר לשחק עם זה גם כאן)package main import ( "fmt" "time" ) func sleepAndSay(s string) { time.Sleep(100 * time.Millisecond) fmt.Println(s) } func main() { go sleepAndSay("world") fmt.Println("hello") time.Sleep(200 * time.Millisecond) }
הפלט יהיה
hello world
כאן אנו יכולים לראות שייבאנו את החבילה TIME ושהכנסנו את כל החבילות המיובאות לתוך סוגריים
זה פשוט בשביל הנוחות כשמייבאים חבילות מרובות.
וכן יצרנו פונציה בשם sleepAndSay עם המשתנה s מסוג סטרינג
בתוך הפונקציה אנו ממתינים 100 מילי שניות
ואז מדפיסים את הערך שקיבלנו במשתנה sבפונקציה הראשית (main)
אנו קוראים ל
sleepAndSay("world")
עם המילה go לפניו
ומיד אחר כך מדפיסים את המילה hello
ואחר כך מחכים עוד 200 מילישניות
כדי שכל הפונקציות שקראנו אליהם באופן אסינכרוני יגמרו לפני שהפונקציה הראשית תגמר.אם לא קלטתם עדיין את העניין?
אפשר לשחק עם הסדר של הפונקציות ולהוסיף ולהוריד go לפני הפונקציות. -
אתר חביב שמציג בצורה מסודרת ופשוטה את GO ואלו כלים היא מספקת
https://gobyexample.com/