Menu

טיפוסי נתונים ב-Golang: int, float64, string, bool, byte, rune

הטיפוסים המובנים של Go: גדלים וטווחים של מספרים שלמים, float32 ו-float64, bool, string, byte ו-rune, מספרים מרוכבים, ערכי אפס, ואיך מדפיסים את הטיפוס של ערך עם %T.

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

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

שימו לב ש-'G' מודפס כ-71 עם הטיפוס int32: תו בגרשיים בודדים הוא rune, כלומר מספר (נקודת הקוד ב-Unicode). rune הוא כינוי של int32 (אותו טיפוס בשם נוסף), ולכן %T מדווח int32. באותו אופן byte מדווח uint8.

מספרים שלמים

טיפוסגודלטווח
int88 סיביות-128 עד 127
int1616 סיביות-32,768 עד 32,767
int3232 סיביותבערך -2.1 מיליארד עד 2.1 מיליארד
int6464 סיביותבערך -9.2 קווינטיליון עד 9.2 קווינטיליון
uint8 (byte)8 סיביות0 עד 255
uint1616 סיביות0 עד 65,535
uint3232 סיביות0 עד בערך 4.3 מיליארד
uint6464 סיביות0 עד בערך 18.4 קווינטיליון
int, uint32 או 64 סיביותגודל המילה של הפלטפורמה
uintptrגודל הפלטפורמהמחזיק ערך של מצביע, לקוד ברמה נמוכה

השתמשו ב-int כברירת מחדל. len() מחזירה int, אינדקסים של slices הם int, ומוני לולאות הם int. בכל פלטפורמה של 64 סיביות int הוא 64 סיביות. פנו לטיפוסים עם גודל מוגדר כשהגודל הוא חלק מחוזה: int32 בפורמט קובץ בינארי, uint8 לבתים גולמיים, int64 לחותמת זמן Unix בננו-שניות.

הימנעו מטיפוסים לא מסומנים (unsigned) עבור כמויות ש"לא יכולות להיות שליליות", כמו ספירות. חיסור מתחת לאפס מתגלגל למספר ענק במקום לייצר מספר שלילי שאפשר היה לתפוס.

גבולות ו-overflow

לחבילת math יש קבוע לכל גבול. בזמן ריצה, חשבון שלמים שחורג מהגבול מתגלגל חזרה בשקט:

בלי panic ובלי שגיאה: 127 + 1 הופך ל--128. רק ביטויים קבועים נבדקים בזמן קומפילציה (var b int8 = 128 לא מתקמפל). אם overflow אפשרי בנתונים שלכם, בדקו לפני הפעולה או השתמשו ב-math/big.

ליטרלים של מספרים שלמים

million := 1_000_000   // underscores for readability (Go 1.13+)
mask := 0xFF           // hexadecimal
perm := 0o755          // octal (also the older form 0755)
flags := 0b1010        // binary

מספרים עשרוניים (floating-point)

טיפוסגודלדיוק
float3232 סיביותבערך 6 עד 9 ספרות משמעותיות
float6464 סיביותבערך 15 עד 17 ספרות משמעותיות

ליטרל עם נקודה עשרונית או מעריך (2.5, 1e6) הוא float64 כברירת מחדל, וחבילת math מקבלת ומחזירה float64. השתמשו בו אלא אם הזיכרון במערך גדול חשוב.

מספרים עשרוניים הם בינאריים, ולכן רוב השברים העשרוניים הם קירובים:

מכאן נובעים שני כללים. אף פעם אל תשוו מספרים עשרוניים עם == אחרי חישוב. ואף פעם אל תשמרו כסף במספר עשרוני: השתמשו במספר שלם של אגורות, או בספרייה עשרונית.

חילוק מספר עשרוני באפס נותן +Inf, -Inf או NaN במקום panic. חילוק מספר שלם באפס גורם ל-panic בזמן ריצה (runtime error: integer divide by zero), ומחלק שהוא אפס קבוע הוא שגיאת קומפילציה.

ערכים בוליאניים

bool מחזיק true או false, וערך האפס שלו הוא false. Go לא מתייחסת למספרים, למחרוזות ריקות או ל-nil כערכים בוליאניים. if count {} היא שגיאת קומפילציה; כתבו if count > 0 {}. האופרטורים הם &&, || ו-!, ו-&& ו-|| מבצעים הערכה מקוצרת.

מחרוזות

string הוא רצף בתים בלתי ניתן לשינוי, בדרך כלל טקסט UTF-8. len(s) סופר בתים, לא תווים:

é תופס שני בתים ב-UTF-8, ולכן len מדווח 6 עבור חמישה תווים. מחרוזות במירכאות כפולות מעבדות תווי escape כמו \n; מחרוזות גולמיות בגרש הפוך (backquote) לא מעבדות אותם, ויכולות להשתרע על כמה שורות. הדף על מחרוזות מכסה את חבילת strings, והדף על runes ו-bytes מסביר את UTF-8 לעומק.

byte ו-rune

כינויזהה ל-מחזיק
byteuint8בית אחד של נתונים גולמיים
runeint32נקודת קוד אחת של Unicode

אלה כינויים, לא טיפוסים חדשים: byte ו-uint8 ניתנים להחלפה בלי המרה. השמות אומרים מה המשמעות של המספר.

מספרים מרוכבים

ל-Go יש טיפוסים מרוכבים מובנים, complex64 ו-complex128, עם real, imag וחבילת math/cmplx:

מעט תוכניות צריכות אותם, אבל עיבוד אותות וחלק מהקוד הנומרי כן.

טיפוסים מורכבים וטיפוסי הפניה

הטיפוסים הבסיסיים מתחברים לטיפוסים מורכבים. לכל אחד מהם יש דף משלו:

טיפוסדוגמהערך אפס
מערך[3]intשלושה אפסים
slice[]intnil
mapmap[string]intnil
structstruct{ X, Y int }כל שדה מאופס
מצביע*intnil
פונקציהfunc(int) intnil
channelchan intnil
interfaceerror, anynil

any הוא כינוי של interface{} (החל מ-Go 1.18) ויכול להחזיק ערך מכל טיפוס.

טיפוסים בעלי שם

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

type Celsius float64
type UserID int64

var t Celsius = 21.5
var f float64 = t // compile error: cannot use t (variable of float64 type Celsius) as float64 value in variable declaration

ההקפדה הזאת היא העיקר: אי אפשר להעביר בטעות UserID למקום שבו מצופה OrderID. המירו במפורש כשזו הכוונה: float64(t). ראו את הדף על המרת טיפוסים לגבי הכללים, ואת פונקציות strconv למעבר בין מספרים למחרוזות.

ערכי אפס

לכל טיפוס יש ערך אפס, שהוא מה שמשתנה מחזיק לפני שהשמתם בו משהו: 0 למספרים, false ל-bool, "" למחרוזות, ו-nil למצביעים, slices, maps, channels, פונקציות ו-interfaces. אין ב-Go משתנים לא מאותחלים.

שאלות נפוצות

מה הגודל של int ב-Go?

int ו-uint הם 64 סיביות בפלטפורמות של 64 סיביות (amd64, arm64) ו-32 סיביות בפלטפורמות של 32 סיביות. אם אתם צריכים גודל קבוע, עבור פורמט קובץ או פרוטוקול רשת, השתמשו ב-int32, int64, uint8 וכן הלאה. למונים, אינדקסים ואורכים רגילים השתמשו ב-int.

איך מדפיסים את הטיפוס של משתנה ב-Go?

השתמשו ב-verb %T: fmt.Printf("%T\n", x) מדפיס int, float64, []string, main.User וכן הלאה. בקוד, reflect.TypeOf(x) מחזירה את אותו מידע כערך שאפשר לבחון.

מה ההבדל בין byte ל-rune ב-Go?

byte הוא כינוי (alias) של uint8 ומחזיק בית אחד של נתונים גולמיים. rune הוא כינוי של int32 ומחזיק נקודת קוד אחת של Unicode. מחרוזת היא רצף של בתים; מעבר עליה עם for range מפענח אותה ל-runes.

האם להשתמש ב-float32 או ב-float64 ב-Go?

השתמשו ב-float64 אלא אם יש לכם סיבה שלא. זה טיפוס ברירת המחדל של ליטרלים עשרוניים, הטיפוס שחבילת math עובדת איתו, ויש לו דיוק של בערך 15 עד 17 ספרות משמעותיות לעומת בערך 6 עד 9 ב-float32. בחרו ב-float32 רק כדי לחסוך חצי מהזיכרון במערכים גדולים או כדי להתאים לפורמט חיצוני.

מה הערך המקסימלי של int ב-Go?

השתמשו בקבועים של חבילת math: math.MaxInt (9223372036854775807 בפלטפורמות של 64 סיביות), math.MinInt, math.MaxInt64, math.MaxUint32 וכן הלאה. חשבון שעובר את הגבול מתגלגל חזרה בשקט בזמן ריצה; הוא לא גורם ל-panic.

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

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

להתחיל