Menu
flag Ar iconالعربيةdown icon

تحويل int إلى string والعكس وتحويل الأنواع في Golang

كيف تحوّل بين الأنواع في Go: من int إلى string ومن string إلى int بـ strconv، ومن الأعداد العشرية إلى الصحيحة، والتحويلات الرقمية بـ T(v)، والبايتات والـ runes، وفخ string(65)، ومعالجة أخطاء التحويل.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

لا تحوّل Go الأنواع ضمنيًا أبدًا. تحوّل بين الأنواع المتوافقة بـ T(v)، وبين الأرقام والنصوص بالحزمة strconv. أكثر تحويلين يُبحث عنهما:

تنسّق strconv.Itoa ("integer to ASCII") قيمة int كنص عشري. وتحلّل strconv.Atoi ("ASCII to integer") النص إلى int وتعيد خطأ عندما لا يكون النص رقمًا صالحًا. افحص ذلك الخطأ دائمًا.

التحويل T(v)

تبدو صياغة التحويل في Go كاستدعاء دالة باسم النوع الهدف. تعمل في ثلاث حالات:

  1. بين الأنواع الرقمية (int وint64 وfloat64 وuint8، ...)،
  2. بين string و[]byte أو []rune،
  3. بين الأنواع التي تتشارك نوعًا أساسيًا (Celsius وfloat64).

اقرأ النتائج بعناية:

  • int(3.9) تساوي 3 وint(-3.9) تساوي -3. التحويل يقتطع نحو الصفر؛ ولا يقرّب. استخدم math.Round أو math.Floor أو math.Ceil أولًا لتختار السلوك. تقرّب math.Round النصف بعيدًا عن الصفر، فتصبح -3.5 مساوية لـ -4.
  • uint8(300) تساوي 44، لأن البتات الثمانية الدنيا وحدها تبقى (300 ناقص 256)، وint8(200) تساوي -56 للسبب نفسه. لا خطأ ولا panic.
  • يتشارك Celsius وfloat64 نوعًا أساسيًا، فيتحوّلان بحرية، لكن صراحة فقط.

القيم في متغيّرات عن قصد. مع الثوابت لا تُترجم التحويلات نفسها.

الثوابت تُفحص، والمتغيّرات لا

تحويل ثابت لا يتّسع خطأ ترجمة. أما تحويل متغيّر بالقيمة نفسها فيلتفّ بصمت:

fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8

وتحويل ثابت غير صحيح إلى نوع صحيح مرفوض أيضًا، بينما تُقتطع القيمة نفسها في متغيّر:

./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int

إذا كانت القيمة العشرية خارج نطاق النوع الصحيح الهدف (مثل int64(1e20))، فالنتيجة تعتمد على التطبيق: amd64 وarm64 مثلًا يعطيان إجابتين مختلفتين. افحص النطاق قبل تحويل القيم غير الموثوقة.

تحويل الأرقام إلى نصوص

منالدالةمثالالنتيجة
intstrconv.Itoa(n)strconv.Itoa(-7)"-7"
int64strconv.FormatInt(n, base)strconv.FormatInt(255, 16)"ff"
uint64strconv.FormatUint(n, base)strconv.FormatUint(5, 2)"101"
float64strconv.FormatFloat(f, fmt, prec, 64)strconv.FormatFloat(3.14159, 'f', 2, 64)"3.14"
boolstrconv.FormatBool(b)strconv.FormatBool(true)"true"
أي شيءfmt.Sprint(v)fmt.Sprint(3.5)"3.5"
أي شيء، منسّقًاfmt.Sprintf(format, v)fmt.Sprintf("%05d", 42)"00042"

تأخذ FormatFloat بايت صيغة ('f' للصيغة الثابتة، و'e' للأسّ، و'g' لأيهما أقصر)، ودقة (-1 تعني "أقل عدد من الأرقام يعيد القيمة نفسها بدقة")، وحجم البتات للعدد العشري الأصلي (64 أو 32).

strconv أسرع من fmt.Sprint، التي تضع القيمة في واجهة وتمرّ بمسار التنسيق العام في fmt. في حلقة ساخنة يظهر هذا الفرق؛ وللتحويلات العرضية اختر ما يُقرأ أفضل.

تحويل النصوص إلى أرقام

إلىالدالةتعيد
intstrconv.Atoi(s)int, error
أي عدد صحيح بإشارةstrconv.ParseInt(s, base, bitSize)int64, error
أي عدد صحيح دون إشارةstrconv.ParseUint(s, base, bitSize)uint64, error
عدد عشريstrconv.ParseFloat(s, bitSize)float64, error
قيمة منطقيةstrconv.ParseBool(s)bool, error

تعيد ParseInt دائمًا int64. يضبط الوسيط bitSize (0 أو 8 أو 16 أو 32 أو 64) النطاق الذي تقبله، فتكون النتيجة مضمونة الاتّساع عند تحويلها إلى نوع أصغر. والأساس base بقيمة 0 يعني "استنتج من البادئة"، فتُحلَّل 0x1f و0o17 و0b101 و1_000 كلها.

أمور تظهرها المخرجات:

  • يفشل " 42". تقبل Atoi إشارة اختيارية وأرقامًا، ولا شيء آخر. المدخلات من bufio تنتهي عادة بـ \n، فأزلها.
  • "4.2" غير صالح لـ Atoi. استخدم ParseFloat للأعداد العشرية.
  • عند خطأ خارج النطاق تعيد ParseInt أكبر قيمة تتّسع (127 لـ int8) مع الخطأ. لا تستخدم القيمة عندما لا يكون الخطأ nil.
  • الأخطاء قيم *strconv.NumError تغلّف strconv.ErrSyntax أو strconv.ErrRange، فتستطيع errors.Is التمييز بينها.

تقبل ParseBool القيم 1 وt وT وTRUE وtrue وTrue وأشكال false المقابلة. أما "yes" و"on" فأخطاء.

فخ string(65)

تحويل عدد صحيح إلى string لا ينتج أرقامًا. بل ينتج الحرف صاحب نقطة رمز Unicode تلك:

n := 65
s := string(n) // "A", not "65"

يقبله المترجم، لكن go vet يبلغ عنه:

./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits

إذا أردت الحرف فعلًا، فقل ذلك بـ rune: string(rune(n)). وإذا أردت الرقم كنص، فاستخدم strconv.Itoa(n). أما تحويل rune أو byte إلى string فلا بأس به وشائع:

النصوص والبايتات والـ runes

تتحوّل string و[]byte و[]rune فيما بينها بـ T(v). كل تحويل ينسخ البيانات، لأن النصوص غير قابلة للتعديل والشرائح قابلة:

حوّل إلى []rune عندما تحتاج الفهرسة أو التعديل بالأحرف؛ وحوّل إلى []byte للإدخال والإخراج والتجزئة والتعديلات على مستوى البايت. صفحة الـ runes والبايتات تشرح UTF-8 بالتفصيل.

التحويل مقابل تأكيد النوع

يغيّر التحويل قيمة من نوع محدّد إلى آخر. أما استخراج القيمة المحدّدة من واجهة (any أو error أو io.Reader) فعملية مختلفة، هي تأكيد النوع:

var v any = 42

n := v.(int)       // type assertion: v holds an int, give it to me
f := float64(n)    // conversion: int to float64
// f := float64(v) // compile error: cannot convert v (variable of interface type any)
//                  // to type float64: need type assertion

أكّد أولًا، ثم حوّل. وصيغة comma-ok n, ok := v.(int) تتجنّب panic عندما يكون النوع خاطئًا.

مرجع سريع

المهمةالشيفرة
من int إلى stringstrconv.Itoa(n)
من int64 إلى stringstrconv.FormatInt(n, 10)
من string إلى intn, err := strconv.Atoi(s)
من string إلى int64n, err := strconv.ParseInt(s, 10, 64)
من string إلى float64f, err := strconv.ParseFloat(s, 64)
من float64 إلى stringstrconv.FormatFloat(f, 'f', -1, 64)
من float64 إلى intint(f) (يقتطع) أو int(math.Round(f))
من int إلى float64float64(n)
من string إلى []byte[]byte(s)
من []byte إلى stringstring(b)
من rune إلى stringstring(r)
من bool إلى stringstrconv.FormatBool(b)
أي قيمة إلى stringfmt.Sprint(v)

الأسئلة الشائعة

كيف أحوّل int إلى string في Go؟

استخدم strconv.Itoa(n): تعيد strconv.Itoa(42) القيمة "42". ولـ int64 استخدم strconv.FormatInt(n, 10). تعمل fmt.Sprint(n) أيضًا مع أي نوع لكنها أبطأ. لا تكتب string(n): فهذا يعامل n كنقطة رمز Unicode، فتكون string(65) مساوية لـ "A".

كيف أحوّل string إلى int في Go؟

استخدم strconv.Atoi، التي تعيد الرقم وخطأ:

n, err := strconv.Atoi("42")
if err != nil {
	// not a valid integer
}

لحجم أو أساس محدّد استخدم strconv.ParseInt(s, 10, 64)، التي تعيد int64. لا تزيل Atoi المسافات، فيكون " 42" خطأ؛ استدعِ strings.TrimSpace أولًا.

كيف أجري cast في Go؟

تسمّيه Go تحويلًا، وصياغته T(v): float64(n) وint(f) و[]byte(s). يعمل بين الأنواع الرقمية، وبين النصوص وشرائح البايتات أو الـ runes، وبين الأنواع التي لها النوع الأساسي نفسه. ولا يحلّل النصوص: تحويل "42" إلى 42 يحتاج strconv. أما استخراج نوع محدّد من واجهة فهو تأكيد نوع، v.(T)، لا تحويل.

كيف أحوّل float إلى int في Go؟

يقتطع int(f) نحو الصفر: int(3.9) تساوي 3 وint(-3.9) تساوي -3. للتقريب استخدم int(math.Round(f)). وإذا كان العدد العشري خارج نطاق النوع الصحيح فالنتيجة تعتمد على التطبيق، فافحص النطاق أولًا عندما تأتي القيمة من مدخلات.

لماذا تعيد string(65) القيمة "A" في Go؟

تحويل عدد صحيح إلى string يفسّره كنقطة رمز Unicode، و65 هي نقطة رمز A. يبلغ go vet عن ذلك: conversion from int to string yields a string of one rune, not a string of digits. استخدم strconv.Itoa(65) لتحصل على "65".

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن