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

Printf وSprintf في Golang: مرجع أفعال التنسيق في fmt

كيف تطبع الحزمة fmt في Go القيم وتنسّقها: Println مقابل Printf مقابل Sprintf مقابل Errorf، الجدول الكامل لأفعال التنسيق (%v و%+v و%d و%s و%q و%f و%T و%w وغيرها)، والعرض والدقة والحشو.

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

للحزمة fmt ثلاث عائلات من دوال الطباعة، ولكل عائلة الأشكال الثلاثة نفسها:

الدالةوجهة المخرجاتالتنسيق
Print، Println، Printfالمخرج القياسيافتراضي، افتراضي بمسافات وسطر جديد، نص تنسيق
Sprint، Sprintln، Sprintfstring معادالأساليب الثلاثة نفسها
Fprint، Fprintln، Fprintfأي io.Writer (ملف، مخزن مؤقّت، ردّ HTTP)الأساليب الثلاثة نفسها
Errorferror معادنص تنسيق، مع %w للتغليف

تضيف Println مسافات بين المعاملات وسطرًا جديدًا في النهاية. أما Printf فلا تضيف شيئًا: تكتب \n بنفسك. وتضيف Print مسافات فقط بين معاملين ليس أي منهما نصًا، وهذا مفاجئ بما يكفي لتستخدم معظم الشيفرات Println أو Printf.

أفعال التنسيق

عامة

الفعلما يطبعهمثال على المخرجات
%vالقيمة بتنسيق افتراضي{Ana 31 [admin]}
%+vالبنى مع أسماء الحقول{Name:Ana Age:31 Tags:[admin]}
%#vصيغة Go للقيمةmain.User{Name:"Ana", Age:31, Tags:[]string{"admin"}}
%Tالنوعmain.User
%%علامة نسبة مئوية حرفية%

%+v هو ما تلجأ إليه عند تتبّع الأخطاء. المؤشر إلى بنية يُطبع بالشكل &{...} لا كعنوان. وتُطبع الخرائط بمفاتيح مرتّبة، فتكون المخرجات ثابتة رغم أن ترتيب المرور على الخريطة عشوائي.

الأعداد الصحيحة

الفعلالمعنىfmt.Sprintf(verb, 255)
%dعشري255
%bثنائي11111111
%oثماني377
%Oثماني مع البادئة 0o0o377
%x / %Xست عشري بأحرف صغيرة أو كبيرةff / FF
%#xست عشري مع البادئة 0x0xff
%cالحرف صاحب نقطة الرمز تلكÿ
%qحرفية حرف بين علامتي اقتباس'ÿ'
%Uصيغة UnicodeU+00FF

الأعداد العشرية

الفعلالمعنىfmt.Sprintf(verb, 1234.5678)
%fعشري، 6 منازل افتراضيًا1234.567800
%.2fعشري، منزلتان1234.57
%eالصيغة العلمية1.234568e+03
%g%e أو %f، أيهما أقصر، دون أصفار زائدة في النهاية1234.5678
%vمثل %g1234.5678

يقرّب %.2f القيمة الثنائية الدقيقة للعدد العشري، فتكون fmt.Sprintf("%.2f", 2.675) مساوية لـ 2.67: أقرب float64 إلى 2.675 أقل منه بقليل. لا تنسّق المال من عدد عشري أبدًا؛ احتفظ بالسنتات في عدد صحيح.

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

الفعلالمعنىfmt.Sprintf(verb, "go\n")
%sالنص كما هوgo ثم سطر جديد
%qبين علامتي اقتباس مزدوجتين مع إظهار رموز الهروب"go\n"
%xست عشري لكل بايت676f0a
% xست عشري مع مسافات67 6f 0a

يطبع %s على []byte محتواها كنص؛ بينما يطبع %v الأرقام ([104 105]).

أنواع أخرى

الفعلالنوعما يطبعه
%tbooltrue أو false
%pمؤشر، شريحة، خريطة، قناة، دالةالعنوان، مثل 0xc000012345
%werror (فقط في Errorf)رسالة الخطأ، ويغلّفه

العرض والدقة والحشو

بين % والفعل يمكنك وضع أعلام وعرض ودقة:

الصيغةالأثر
%5dعرض 5، محاذاة إلى النهاية (حشو بمسافات قبل القيمة)
%-5dعرض 5، محاذاة إلى البداية
%05dحشو بالأصفار
%.2fرقمان بعد الفاصلة العشرية
%8.2fعرض 8 ومنزلتان عشريتان
%.3s3 أحرف على الأكثر من النص
%+dإظهار الإشارة دائمًا
%*dالعرض مأخوذ من الوسيط التالي

لاحظ أن %.0f للقيمة 2.5 تطبع 2: تقرّب Go هنا النصف إلى الزوجي. يعدّ العرض الـ runes في النصوص لا أعمدة العرض، فقد تُفسد أحرف CJK والرموز التعبيرية محاذاة الجدول. للأعمدة المحاذاة ذات النصوص المتغيّرة، تتولّى text/tabwriter القياس نيابة عنك.

فهارس الوسائط

يختار %[n] وسيطًا بموقعه، وهذا يتيح لك إعادة استخدامه:

fmt.Printf("%[2]s %[1]s\n", "world", "hello") // hello world
fmt.Printf("%d %[1]x %[1]b\n", 10)             // 10 a 1010

Errorf و%w

تبني fmt.Errorf قيمة error من نص تنسيق. ومع %w تغلّف أيضًا خطأ آخر، فيستطيع المستدعون اكتشاف الأصل:

استخدم %w عندما قد يحتاج المستدعون إلى فحص السبب، و%v عندما تخفيه عمدًا. منذ Go 1.20 يمكن أن يحتوي استدعاء Errorf واحد عدة أفعال %w. صفحة معالجة الأخطاء تشرح التغليف بالتفصيل.

تنسيق مخصّص بـ String()

أي نوع له تابع String() string يتحكّم في طريقة عرض %v و%s وPrintln له:

يتجاوز %d التابع String() ويطبع الرقم الأساسي. في أنواع الأخطاء التابع المقابل هو Error() string، وله الأسبقية على String().

عندما يكون الفعل خاطئًا

لا تسبّب fmt أبدًا panic بسبب تنسيق خاطئ. بل تطبع المشكلة في مكانها:

fmt.Printf("%d\n", "oops")
fmt.Printf("%d %d\n", 1)
fmt.Printf("%d\n", 1, 2)
%!d(string=oops)
1 %!d(MISSING)
1
%!(EXTRA int=2)

هذه المخرجات تصل غالبًا إلى الإنتاج لأنها لا توقف شيئًا. يكتشف go vet الحالات الثلاث وقت البناء:

./main.go:8:2: fmt.Printf format %d has arg "oops" of wrong type string
./main.go:9:2: fmt.Printf format %d reads arg #2, but call has 1 arg
./main.go:10:2: fmt.Printf call needs 1 arg but has 2 args

ملاحظات عن الأداء

تأخذ fmt كل وسيط كـ any وتفحص نوعه وقت التشغيل (وتلجأ إلى الانعكاس reflection للبنى والشرائح والخرائط)، وهذا مقبول للتسجيل والمخرجات لكنه ملموس في الحلقات الضيّقة. لتحويل رقم واحد، strconv.Itoa وstrconv.FormatFloat أسرع من Sprintf. ولبناء نص طويل في حلقة، اكتب في strings.Builder بـ fmt.Fprintf(&b, ...) بدل ضمّ نتائج Sprintf.

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

ما الفرق بين Println وPrintf وSprintf في Go؟

تطبع fmt.Println وسائطها مفصولة بمسافات مع سطر جديد في النهاية. وتطبع fmt.Printf حسب نص تنسيق ولا تضيف سطرًا جديدًا. وتنسّق fmt.Sprintf بالطريقة نفسها التي تنسّق بها Printf لكنها تعيد النتيجة كنص بدل طباعتها. وتفعل fmt.Errorf الشيء نفسه وتعيد error.

كيف أطبع بنية مع أسماء حقولها في Go؟

استخدم %+v: تطبع fmt.Printf("%+v\n", user) القيمة {Name:Ana Age:31}. أما %v فيطبع القيم فقط، {Ana 31}، و%#v يطبع صيغة Go مع النوع، main.User{Name:"Ana", Age:31}.

كيف أنسّق عددًا عشريًا بمنزلتين عشريتين في Go؟

استخدم %.2f: تعيد fmt.Sprintf("%.2f", 3.14159) القيمة "3.14". أضف عرضًا لمحاذاة الأعمدة، %8.2f، أو علامة ناقص للمحاذاة إلى البداية، %-8.2f. وتعطي strconv.FormatFloat(f, 'f', 2, 64) النتيجة نفسها دون نص تنسيق.

ماذا يفعل %w في fmt.Errorf؟

ينسّق %w الخطأ مثل %v ويغلّفه أيضًا، فيحمل الخطأ الجديد الأصلي. وعندها تستطيع errors.Is وerrors.As إيجاد الخطأ المغلّف: err := fmt.Errorf("load config: %w", os.ErrNotExist) تجعل errors.Is(err, os.ErrNotExist) صحيحة. يعمل %w فقط في fmt.Errorf.

لماذا تظهر في مخرجاتي %!d(string=...)؟

الفعل لا يطابق نوع الوسيط، مثلًا %d مع نص. تطبع fmt المشكلة في مكانها بدل panic: %!d(string=oops). الوسائط الناقصة تطبع %!d(MISSING) والزائدة %!(EXTRA int=2). يكتشف go vet الحالات الثلاث قبل تشغيل البرنامج.

Coddy programming languages illustration

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

ابدأ الآن