Putting It All Together
Hammasini birlashtirish
Shu kursda o'rgangan hamma narsani — ulanish, Exec, Query, QueryRow, Prepared Statements, NULL, tranzaksiyalar — haqiqiy loyihada qanday ko'rinishda birlashishini yakuniy marta ko'rib chiqamiz.
package repository
import (
"database/sql"
"fmt"
)
type UserRepo struct {
db *sql.DB
}
func NewUserRepo(db *sql.DB) *UserRepo {
return &UserRepo{db: db}
}
func (r *UserRepo) Create(name string, age int) (int64, error) {
result, err := r.db.Exec(
"INSERT INTO users (name, age) VALUES ($1, $2)", name, age,
)
if err != nil {
return 0, fmt.Errorf("UserRepo.Create: %w", err)
}
return result.LastInsertId()
}
func (r *UserRepo) FindByID(id int64) (string, error) {
var name string
err := r.db.QueryRow("SELECT name FROM users WHERE id = $1", id).Scan(&name)
if err == sql.ErrNoRows {
return "", fmt.Errorf("UserRepo.FindByID: foydalanuvchi topilmadi")
}
if err != nil {
return "", fmt.Errorf("UserRepo.FindByID: %w", err)
}
return name, nil
}Diqqat qiling: bu kod — shu kursda ko'rgan hamma texnikaning ("Add Context to Errors" darsidagi %w bilan xato o'rash, "Sentinel Errors"dagi sql.ErrNoRows tekshiruvi, "Accept Interfaces, Return Structs"dagi struct qaytarish) tabiiy davomi. UserRepo — ma'lumotlar bazasi bilan ishlashni qolgan kod qismidan ajratadigan "repository" naqshi, u "Code Organization" kursida ko'rgan "bitta paket, bitta maqsad" tamoyiliga mos keladi.
E'tibor bering: haqiqiy loyihada ? o'rniga $1, $2 (PostgreSQL uslubi) yoki boshqa belgi ishlatilishi mumkin — bu drayverga bog'liq, lekin database/sqlning o'zi bergan naqsh (Exec, Query, QueryRow, Scan, tranzaksiyalar) har qanday drayver bilan bir xil ishlaydi.
Key Takeaway
Key Takeaway:
database/sqlning kuchi — bir marta o'rgangan naqsh (Exec/Query/Scan/tranzaksiya) istalgan ma'lumotlar bazasi bilan, faqat drayverni almashtirib, ishlayverishida.