Menu

מה זה Golang? שפת Go בהסבר עם דוגמאות

Go (שנקראת לעיתים קרובות Golang) היא שפה מהודרת עם טיפוסים סטטיים שתוכננה ב-Google לבניית שרתים וכלים מהירים ואמינים. הדף מסביר מה היא, למה משתמשים בה ואיפה היא פחות מתאימה.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

Go היא שפת תכנות מהודרת עם טיפוסים סטטיים שנוצרה ב-Google. היא מייצרת קובץ בינארי נייטיב יחיד, מתקמפלת תוך שניות, יש לה garbage collection, ויש לה מקביליות מובנית בשפה דרך goroutines ו-channels. הבית העיקרי שלה הוא תוכנה בצד השרת: APIs, שירותי רשת, וכלי שורת הפקודה והענן שמריצים אותם.

הנה תוכנית Go מלאה. לחצו על Run.

כל תוכנית Go מתחילה ב-package main ב-func main(). := מצהיר על משתנה ומסיק את הטיפוס שלו (כאן []string, slice של מחרוזות). range עובר על ה-slice ונותן אינדקס וערך. fmt ו-strings מגיעות מהספרייה הסטנדרטית, שהיא גדולה מספיק כדי שהרבה תוכניות לא ייבאו שום דבר אחר.

Go מול Golang: השם

השפה נקראת Go. "Golang" הוא כינוי מהאתר הראשון של הפרויקט, golang.org (האתר נמצא היום ב-go.dev). אנשים המשיכו להשתמש בו כי חיפוש של "go" ברשת מחזיר הכול חוץ מהשפה. התיעוד הרשמי אומר "Go", אבל "golang" הוא המונח שכמעט כולם מקלידים בתיבת חיפוש, ושניהם אותו דבר. אין מוצר או דיאלקט נפרד בשם "Golang".

מי יצר את Go ולמה

Robert Griesemer, Rob Pike ו-Ken Thompson התחילו לתכנן את Go ב-Google ב-2007. היא שוחררה כקוד פתוח בנובמבר 2009, ו-Go 1.0 יצאה במרץ 2012.

המניע היה מעשי. בסיסי הקוד הגדולים של Google ב-C++ וב-Java לקחו הרבה זמן לבנייה, היה קשה לנהל את גרפי התלויות, ומכונות מרובות ליבות ושירותי רשת היו הנורמה אבל כתיבת קוד מקבילי הייתה מועדת לשגיאות. התכנון של Go עונה על הבעיות האלה ישירות:

  • בנייה מהירה. הייבוא מפורש, ייבוא שלא בשימוש הוא שגיאת הידור, והמהדר לא מפענח headers מחדש, כך שתוכניות גדולות נבנות תוך שניות.
  • שפה פשוטה. מעט מילות מפתח, לולאה אחת (for), בלי ירושה, בלי exceptions. קוד שכתבו אנשים שונים נוטה להיראות דומה, וזה עוזר בסקירות קוד בצוות גדול.
  • מקביליות כיכולת של השפה. הפעלה של משימה מקבילית היא מילת מפתח אחת, go, ו-channels מאפשרים למשימות לתקשר.
  • פריסה קלה. הפלט הוא קובץ בינארי אחד שמעתיקים לשרת. בדרך כלל הוא מקושר סטטית; כש-cgo מופעל, חבילות כמו net יכולות להתקשר לספריית ה-C של המערכת, ו-CGO_ENABLED=0 מכבה את זה.

Go 1.0 הגיעה גם עם הבטחת התאימות של Go 1: תוכניות שנכתבו ל-Go 1.0 ממשיכות להתקמפל ולרוץ בגרסאות 1.x מאוחרות יותר. בפועל זה אומר ששדרוג ה-toolchain כמעט אף פעם לא שובר את הקוד שלכם, וזו סיבה גדולה לכך שצוותים סומכים על Go לשירותים ארוכי טווח.

למה משתמשים ב-Golang

Go הכי חזקה במקומות שבהם תוכנית מדברת עם רשת, רצה הרבה זמן וצריכה להיות קלה לשילוח:

תחוםדוגמאות
Web APIs ו-microservicesשירותי HTTP ו-gRPC, backends לאפליקציות web ומובייל
כלי ענן ותשתיתDocker, Kubernetes, Terraform, Prometheus
כלי שורת פקודהCLIs למפתחים שמשוחררים כקובץ בינארי יחיד לכל פלטפורמה
רשתותproxies, load balancers, שרתי DNS
צינורות נתוניםworkers שקוראים מתורים, ממירים רשומות וכותבים למסדי נתונים

היא מתאימה פחות לאפליקציות desktop עם ממשק גרפי, לאפליקציות מובייל, ל-front ends בדפדפן ולעבודה נומרית או של machine learning, שבהן לאקוסיסטמים אחרים יש ספריות טובות בהרבה.

יכולות מרכזיות, עם קוד

טיפוסים סטטיים עם הסקה

לכל משתנה יש טיפוס שנקבע בזמן הידור, אבל כמעט אף פעם לא כותבים אותו. := מסיק אותו:

Go אף פעם לא ממירה בין טיפוסים מספריים בשקט. count * price לא מתקמפל, כי אחד הוא int והשני float64; כותבים float64(count) בעצמכם. זה מונע באגים שקטים של קיצוץ ושל דיוק.

שגיאות הן ערכים

ל-Go אין exceptions. פונקציה שיכולה להיכשל מחזירה error כתוצאה האחרונה שלה, והקורא בודק אותה:

הדפוס if err != nil הוא השורה הכי מזוהה בקוד Go. הוא מילולי, וזו בדיוק הכוונה: כל מקום שבו תוכנית יכולה להיכשל גלוי במקום שבו זה קורה. ראו טיפול בשגיאות לעטיפה ולבדיקה של שגיאות.

Goroutines ו-channels

goroutine היא פונקציה שרצה במקביל לשאר התוכנית. היא עולה כמה קילובייטים של stack, כך שהרצה של אלפים מהן היא דבר רגיל. channels מעבירים ערכים בין goroutines בבטחה:

שלוש ה-goroutines רצות במקביל, כך ששלוש השורות יכולות להיות מודפסות בכל סדר. הריצו את זה כמה פעמים ואולי תראו סדרים שונים. main מקבלת בדיוק שלושה ערכים, כך שהיא מחכה לכולם לפני שהיא יוצאת.

Interfaces בלי "implements"

טיפוס מממש interface רק בזכות זה שיש לו את המתודות הנכונות. אין מילת מפתח implements:

Rect ו-Circle אף פעם לא מזכירים את Shape, ובכל זאת אפשר לשמור את שניהם ב-[]Shape. זה מאפשר להגדיר interface בחבילה שמשתמשת בו, הרבה אחרי שהטיפוסים הקונקרטיים נכתבו.

Toolchain אחד

הפקודה go עושה הכול: go run מהדרת ומריצה, go build יוצרת קובץ בינארי, go test מריצה בדיקות, go fmt מעצבת קוד, go vet תופסת מבנים חשודים, ו-go mod מנהלת תלויות. יש סגנון עיצוב רשמי אחד, שנאכף על ידי gofmt, כך שבפרויקטים של Go לא מתווכחים על סוגריים מסולסלים או הזחה.

מה Go משאירה בחוץ בכוונה

חלק מהיכולות הנפוצות בשפות אחרות חסרות בכוונה:

  • אין מחלקות או ירושה. משתמשים ב-structs, מתודות, interfaces והטמעה.
  • אין exceptions. שגיאות הן ערכים מוחזרים. panic קיים, אבל הוא מיועד לבאגים, לא לכישלונות רגילים.
  • אין אופרטור טרנרי. כותבים if/else.
  • אין מילת מפתח while. for מכסה כל לולאה.
  • אין overloading של פונקציות או ארגומנטים עם ערכי ברירת מחדל.
  • Generics רק מאז Go 1.18, ומוגבלים בכוונה בהשוואה ל-templates של C++ או ל-generics של Java.

החסרונות, בכנות

מילוליות. בדיקות שגיאה מפורשות והיעדר קיצורי דרך כמו האופרטור הטרנרי הופכים קוד Go לארוך יותר מקוד מקביל ב-Python או ב-Kotlin. קל לקרוא אותו; כתיבתו לוקחת יותר שורות.

Garbage collection. לאוסף של Go יש זמני השהיה נמוכים, אבל הוא עדיין garbage collector. למערכות זמן אמת קשיחות או לקוד שבו כל הקצאה חשובה, C, C++ או Rust נותנות יותר שליטה.

ערכי nil. ל-Go יש מצביעים, maps, slices ו-interfaces שהם nil. dereference למצביע nil הוא panic בזמן ריצה, והמהדר לא מונע אותו כמו שמערכת הטיפוסים של Rust עושה.

מערכת טיפוסים קטנה. אין sum types, אין enums (בונים אותם עם קבועים ו-iota), ו-generics שמכסים מקרים נפוצים אבל לא תכנות מתקדם ברמת הטיפוסים.

פערים באקוסיסטם. הספריות לשירותי web, מסדי נתונים ו-APIs של ענן מצוינות. לממשקים גרפיים, חישוב מדעי ו-machine learning, ל-Python, ל-C++ או ל-Julia יש הרבה יותר.

Go בהשוואה לשפות אחרות

GoPythonJavaRust
טיפוסיםסטטייםדינמייםסטטייםסטטיים
רצה כקובץ בינארי נייטיבinterpreterJVM bytecodeקובץ בינארי נייטיב
זיכרוןgarbage collectiongarbage collectiongarbage collectionownership, בלי GC
מקביליותgoroutines, channelsthreads, asyncio (ה-GIL מגביל מקביליות CPU)threads, virtual threadsthreads, async
עקומת למידהנמוכהנמוכהבינוניתגבוהה

בחרו ב-Go כשרוצים ביצועים של שפה מהודרת ופריסה פשוטה בלי עקומת הלמידה של Rust או הטקסיות של Java.

האם שווה ללמוד Go?

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

כדי להתחיל לכתוב Go על המחשב שלכם, התקינו את Go, ואז עברו על הדף של hello world, שמסביר כל שורה בתוכנית ראשונה.

שאלות נפוצות

למה משתמשים ב-Golang?

בעיקר לתוכנות backend ותשתית: שרתי web ו-APIs, microservices, כלי שורת פקודה, קוד רשת וכלי ענן. Docker, Kubernetes, Terraform ו-Prometheus כולם כתובים ב-Go. משתמשים בה לעיתים רחוקות לממשקים גרפיים של desktop, לאפליקציות מובייל או ל-data science.

האם Go ו-Golang זה אותו דבר?

כן. השם של השפה הוא Go. "Golang" מגיע מכתובת האתר המקורית, golang.org, ונדבק כי קשה לחפש את המילה "go". שני השמות מתייחסים לאותה שפה ולאותו toolchain.

מי יצר את שפת התכנות Go?

Robert Griesemer, Rob Pike ו-Ken Thompson תכננו את Go ב-Google החל מ-2007. היא הוכרזה כקוד פתוח בנובמבר 2009, ו-Go 1.0, הגרסה שהתחילה את הבטחת התאימות של Go, יצאה במרץ 2012.

האם קל ללמוד Go?

השפה עצמה קטנה: 25 מילות מפתח, מבנה לולאה אחד, ומפרט קצר שאפשר לקרוא בצהריים אחד. רוב המתכנתים עם ניסיון בשפה אחרת כותבים Go שעובד תוך ימים. החלקים שלוקחים יותר זמן הם הניבים: טיפול מפורש בשגיאות, interfaces, וכתיבת קוד מקבילי נכון עם goroutines ו-channels.

האם Go מהודרת או מפורשת?

מהודרת. go build מייצרת קובץ בינארי בקוד מכונה נייטיב, בלי תלות ב-interpreter או במכונה וירטואלית. גם go run מהדרת; היא פשוט בונה למיקום זמני ומריצה את התוצאה.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל