مقدمة: لماذا Go وقواعد البيانات هما الثنائي المثالي
لغة البرمجة Go (Golang) اكتسبت شعبية بفضل أدائها العالي، ودعمها المدمج للتزامن، وسهولة النشر. لكن القوة الحقيقية لـ Go تتجلى عند العمل مع قواعد البيانات. سواء كانت PostgreSQL العلائقية أو MongoDB الموجهة للمستندات، توفر Go أدوات أنيقة للتفاعل الفعال مع البيانات.
في هذه المقالة، سنستعرض الجوانب العملية للاتصال، وتنفيذ عمليات CRUD، وتحسين استعلامات PostgreSQL وMongoDB باستخدام Go. ستتعلم كيفية استخدام الحزم القياسية والمشغلات الشائعة لكتابة كود موثوق وسريع.
1. العمل مع PostgreSQL في Go
للعمل مع PostgreSQL في Go، يُستخدم الحزمة القياسية database/sql مع مشغل pgx أو lib/pq. يُوصى باستخدام pgx نظرًا لأدائه الأفضل ودعمه للميزات المتقدمة في PostgreSQL.
1.1. التثبيت والاتصال
قم بتثبيت المشغل عبر go modules:
go get github.com/jackc/pgx/v5مثال على الاتصال بقاعدة البيانات:
package main
import ( "context" "fmt" "github.com/jackc/pgx/v5/pgxpool" "log")
func main() { dsn := "postgres://user:password@localhost:5432/mydb?sslmode=disable" pool, err := pgxpool.New(context.Background(), dsn) if err != nil { log.Fatal("Unable to connect to database:", err) } defer pool.Close()
fmt.Println("Connected to PostgreSQL!")}نصيحة: استخدم مجموعة الاتصالات (pgxpool) في بيئة الإنتاج — فهذا يقلل من التكاليف الإضافية لإنشاء اتصالات جديدة.
1.2. عمليات CRUD
لنستعرض العمليات الأساسية باستخدام جدول users كمثال:
// CREATEfunc createUser(pool *pgxpool.Pool, name string, email string) (int, error) { var id int err := pool.QueryRow(context.Background(), "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id", name, email).Scan(&id) if err != nil { return 0, err } return id, nil}
// READfunc getUser(pool *pgxpool.Pool, id int) (string, string, error) { var name, email string err := pool.QueryRow(context.Background(), "SELECT name, email FROM users WHERE id = $1", id).Scan(&name, &email) if err != nil { return "", "", err } return name, email, nil}
// UPDATEfunc updateUserEmail(pool *pgxpool.Pool, id int, newEmail string) error { _, err := pool.Exec(context.Background(), "UPDATE users SET email = $1 WHERE id = $2", newEmail, id) return err}
// DELETEfunc deleteUser(pool *pgxpool.Pool, id int) error { _, err := pool.Exec(context.Background(), "DELETE FROM users WHERE id = $1", id) return err}لاحظ استخدام الاستعلامات المُعلمة مع $1، $2 — فهذا يحمي من هجمات SQL injection.
1.3. المعاملات (Transactions)
يدعم PostgreSQL المعاملات، وهو أمر بالغ الأهمية لسلامة البيانات:
func transferMoney(pool *pgxpool.Pool, fromID, toID int, amount float64) error { tx, err := pool.Begin(context.Background()) if err != nil { return err } defer tx.Rollback(context.Background()) // التراجع عند الخطأ
_, err = tx.Exec(context.Background(), "UPDATE accounts SET balance = balance - $1 WHERE id = $2", amount, fromID) if err != nil { return err }
_, err = tx.Exec(context.Background(), "UPDATE accounts SET balance = balance + $1 WHERE id = $2", amount, toID) if err != nil { return err }
return tx.Commit(context.Background())}2. العمل مع MongoDB في Go
MongoDB هي قاعدة بيانات