مقدمة: الأساطير والواقع لمبرمج Go
\n\nفي مجتمع تكنولوجيا المعلومات، هناك رأيان متعارضان حول عمل مطور Go. يقول البعض إنها جنة للمثالي: كتابة صارمة للأنواع، عدم وجود وراثة للفئات، وترجمة فائقة السرعة. ويقول آخرون إنها عبارة عن if err != nil لا نهاية لها وكفاح مع الأدوية العامة (على الرغم من إضافتها بالفعل).
أين الحقيقة؟ كيف يبدو يوم عمل مطور Go في شركة متوسطة تكتب خدمات مصغرة عالية التحميل؟ اليوم سأفتح باب واقعي. لا ماء - فقط كود وأدوات وحالات حقيقية.
\n\nأعمل في شركة منتجات حيث Golang هي اللغة الأساسية للواجهة الخلفية. مجموعتنا التقنية: gRPC، PostgreSQL، Kafka، Kubernetes. قصة نموذجية لـ التطوير بلغة Go. لنبدأ.
\n\n08:30 - الصباح: الخطة ومراجعة الكود
\n\nلا يبدأ اليوم بالقهوة، بل بتصفح الإشعارات في GitLab وSlack. بينما يكون العقل منتعشًا، هذا هو أفضل وقت لمراجعة طلبات الدمج للزملاء.
\n\nالروتين الصباحي: ما الذي أتحقق منه أولاً؟
\n- \n
- أخطاء CI/CD - إذا فشل البناء ليلاً، فهذه هي المهمة الأولى. \n
- تعليقات على كودي - في Go، من المعتاد إجراء مراجعات مفصلة. \n
- رسوم بيانية للمراقبة - هل انخفض زمن الاستجابة بعد النشر أمس؟ \n
بالمناسبة، عن مراجعة الكود. هناك قاعدة غير مكتوبة في مجتمع Go: يجب أن يكون الكود بسيطًا. إذا كتبت شيئًا معقدًا، سترفض مراجعتك. مثال على تعليق نموذجي من كبير المطورين:
\n\n// سيء: تجريد مفرط\ntype Processor interface {\n Process(ctx context.Context, data []byte) ([]byte, error)\n}\n\n// جيد: مجرد دالة\nfunc Process(ctx context.Context, data []byte) ([]byte, error) {\n // منطق\n}\n\n\nفي الساعة 09:00 - الاجتماع اليومي. لا نضيع الوقت في قصص طويلة. الشكل: ماذا فعلت أمس، ماذا سأفعل اليوم، هل هناك عوائق. لا "كيف كان مساؤك".
\n\n09:30 - الغوص في الكود: كتابة خدمة مصغرة بلغة Go
\n\nاليوم على جدول الأعمال - تحسين خدمة الإشعارات. هذه خدمة مصغرة بلغة Go كلاسيكية تستقبل الأحداث من Kafka وترسل بريدًا إلكترونيًا/دفعًا. المهمة: إضافة دعم للقوالب.
\n\nأولاً، أفتح هيكل المشروع. في Go، من المعتاد استخدام شجرة مجلدات بسيطة:
\n\nnotifier/\n├── cmd/\n│ └── server/\n│ └── main.go\n├── internal/\n│ ├── handler/\n│ ├── service/\n│ └── repository/\n├── pkg/\n│ └── models/\n└── go.mod\n\n\nأبدأ بنموذج البيانات. في Go، للعمل مع قاعدة البيانات، غالبًا ما يستخدمون Go ORM (مثل GORM) أو استعلامات SQL نقية عبر sqlx. أنا أفضل sqlx - سحر أقل، تحكم أكثر.
\n\ntype Template struct {\n ID int64 `db:"id"`\n Name string `db:"name"`\n Content string `db:"content"`\n CreatedAt time.Time `db:"created_at"`\n}\n\nfunc (r *Repository) GetTemplateByName(ctx context.Context, name string) (*Template, error) {\n var t Template\n err := r.db.GetContext(ctx, &t, "SELECT * FROM templates WHERE name = $1", name)\n if err != nil {\n return nil, fmt.Errorf("get template: %w", err)\n }\n return &t, nil\n}\n\n\nلاحظ معالجة الأخطاء. في Golang لا يوجد try-catch. يتم التحقق من كل استدعاء دالة بحثًا عن الأخطاء. هذا ليس خطأ، بل ميزة - يصبح الكود قابلاً للتنبؤ. في 5 سنوات من العمل، لم أواجه أبدًا مؤشرًا فارغًا غير متوقع في الإنتاج.
\n\n11:00 - التكامل مع gRPC
\n\nالمرحلة التالية - إضافة نقطة نهاية gRPC للوحة الإدارة. في التطوير بلغة Go الحديث، أصبح gRPC معيارًا للخدمات الداخلية. إنه أسرع من REST ويولد العملاء تلقائيًا.
\n\nأولاً، أصف ملف proto:
\n\nsyntax = "proto3";\n\npackage notifier;\n\nservice TemplateService {\n rpc CreateTemplate (CreateTemplateRequest) returns (TemplateResponse);\