Go و PostgreSQL: دليل شامل للتكامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا Go و PostgreSQL هما الثنائي المثالي؟

\n\n

في عالم تطوير الواجهة الخلفية، أثبت كل من Go (أو Golang) و PostgreSQL أنهما ثنائي قوي لبناء أنظمة عالية التحميل وموثوقة. يمنحنا Go أداءً لا يُصدق، وبساطة، ودعمًا ممتازًا للتزامن، بينما PostgreSQL هي قاعدة بيانات صناعية غنية بالميزات والموثوقية وقابلية التوسع. بدمجهما، تحصل على مجموعة قادرة على تحمل أعباء الشركات الناشئة ومتطلبات المشاريع المؤسسية.

\n\n

في هذه المقالة، لن نمر فقط على بناء الجملة. سنقوم بإنشاء دليل عملي كامل: من تثبيت المشغل إلى تحسين مجمع الاتصالات والعمل مع المعاملات. ستتعلم كيفية تجنب الأخطاء الشائعة وكتابة كود فعال بلغة Go للعمل مع PostgreSQL. هيا بنا!

\n\n

البدء: اختيار المشغل والاتصال

\n\n

أول ما يجب فعله هو تثبيت المشغل. في عالم Go، هناك مرشحان رئيسيان:

\n
    \n
  • lib/pq — كلاسيكي، بسيط، لكنه لم يعد مدعومًا بنشاط.
  • \n
  • pgx — حديث، سريع، يتطور بنشاط، ويدعم المزيد من ميزات PostgreSQL (مثل COPY، LISTEN/NOTIFY، المصفوفات). أوصي به تحديدًا.
  • \n
\n

نقوم بتثبيت pgx:

\n
go get github.com/jackc/pgx/v5
\n\n

الآن لنكتب كود الاتصال بقاعدة البيانات. لننشئ ملف main.go:

\n
package main\n\nimport (\n    "context"\n    "fmt"\n    "log"\n\n    "github.com/jackc/pgx/v5/pgxpool"\n)\n\nfunc main() {\n    // رابط الاتصال: المستخدم، كلمة المرور، المضيف، المنفذ، اسم قاعدة البيانات\n    dsn := "postgres://myuser:mypassword@localhost:5432/mydb?sslmode=disable"\n\n    // إنشاء مجمع اتصالات (connection pool)\n    pool, err := pgxpool.New(context.Background(), dsn)\n    if err != nil {\n        log.Fatalf("فشل إنشاء المجمع: %v", err)\n    }\n    defer pool.Close()\n\n    // التحقق من الاتصال\n    err = pool.Ping(context.Background())\n    if err != nil {\n        log.Fatalf("فشل الاتصال: %v", err)\n    }\n\n    fmt.Println("تم الاتصال بنجاح بـ PostgreSQL!")\n}\n
\n

لاحظ: نحن نستخدم pgxpool، وليس اتصالًا بسيطًا. مجمع الاتصالات هو أمر لا غنى عنه للإنتاج. يسمح بإعادة استخدام الاتصالات، وتجنب التكاليف الإضافية لإنشائها وإغلاقها.

\n\n

عمليات CRUD: إنشاء، قراءة، تحديث، حذف

\n\n

الآن دعنا ننفذ العمليات الكلاسيكية على جدول users. لنفترض أن لدينا الهيكل التالي:

\n
type User struct {\n    ID   int\n    Name string\n    Age  int\n}\n
\n\n

إنشاء الجدول (Create)

\n

من الأفضل تنفيذ الترحيلات باستخدام أدوات منفصلة، لكن كمثال سأعرض كيفية تنفيذ SQL خام:

\n
func createTable(ctx context.Context, pool *pgxpool.Pool) error {\n    query := `\n        CREATE TABLE IF NOT EXISTS users (\n            id SERIAL PRIMARY KEY,\n            name TEXT NOT NULL,\n            age INT NOT NULL\n        );\n    `\n    _, err := pool.Exec(ctx, query)\n    return err\n}\n
\n\n

إضافة سجل (Insert)

\n

نستخدم QueryRow لإرجاع المعرف المُنشأ:

\n
func createUser(ctx context.Context, pool *pgxpool.Pool, user *User) error {\n    query := `INSERT INTO users (name, age) VALUES ($1, $2) RETURNING id`\n    err := pool.QueryRow(ctx, query, user.Name, user.Age).Scan(&user.ID)\n    return err\n}\n
\n\n

قراءة سجل (Select)

\n
func getUserByID(ctx context.Context, pool *pgxpool.Pool, id int) (*User, error) {\n    query := `SELECT id, name, age FROM users WHERE id = $1`\n    user := &User{}\n    err := pool.QueryRow(ctx, query, id).Scan(&user.ID, &user.Name, &user.Age)\n    if err != nil {\n        return nil, err\n    }\n    return user, nil\n}\n
\n\n

التحديث والحذف (Update

المدونات

توصيات الكتب