Go Project
Berikut adalah best practice Go Project yang sudah diperbarui dengan poin-poin tambahan dan elaborasi lebih dalam:
1. Logging & Observabilityβ Slog & MultiwriterGunakan slog sebagai structured logger bawaan Go 1.21 ke atas.
Manfaatkan multiwriter untuk menulis log ke beberapa output sekaligus, misalnya file dan stdout:
logger := slog.New(slog.NewJSONHandler(io.MultiWriter(os.Stdout, logFile), nil)) slog.SetDefault(logger)
Pastikan log mencatat trace ID dan context untuk debugging lebih mudah.
β Log File RotationGunakan lumberjack untuk merotasi log dan menghindari file log membengkak:
logFile := &lumberjack.Logger{ Filename: "app.log", MaxSize: 10, // MB MaxBackups: 3, MaxAge: 30, // days Compress: true, }
2. Routing & API Frameworkβ Go ChiGunakan chi untuk router yang ringan dan fleksibel dibandingkan
net/http
.Support middleware, grouping routes, dan parameterized routing:
r := chi.NewRouter() r.Use(middleware.Logger) r.Get("/users/{id}", getUserHandler)
3. Database & Query Handlingβ PostgresGunakan pgx daripada database/sql untuk Postgres karena lebih cepat dan efisien.
Pastikan connection pooling optimal dengan pgxpool.
β Raw Query (Instead of ORM like GORM)Hindari ORM seperti GORM untuk query kompleks agar lebih optimal.
Gunakan pgx.NamedArgs atau query builder ringan seperti squirrel jika diperlukan.
db.Exec("INSERT INTO users (name, email) VALUES ($1, $2)", name, email)
β Transaction HandlingGunakan manual transaction handling dengan
BEGIN
,COMMIT
,ROLLBACK
.Terapkan unit of work pattern untuk menghindari transaksi yang tidak terkelola dengan baik.
tx, err := db.Begin() if err != nil { return err } defer tx.Rollback() _, err = tx.Exec("UPDATE users SET balance = balance - $1 WHERE id = $2", amount, userID) if err != nil { return err } return tx.Commit()
4. Configuration Managementβ Environment-Based ConfigGunakan Viper atau envconfig untuk mengelola konfigurasi dari environment variables.
Hindari hardcoded config di dalam kode.
5. Dependency Injection (DI)β Wire atau FxGunakan Google Wire atau Fx untuk dependency injection agar kode lebih terstruktur.
Jika ingin lebih ringan, gunakan manual DI dengan constructor functions.
6. Error Handling yang Konsistenβ Sentinel Errors & WrappingGunakan sentinel errors untuk kode error yang bisa dikenali.
Gunakan fmt.Errorf atau errors.Join untuk wrapping error dengan konteks tambahan.
7. Context Managementβ Timeout & DeadlineSelalu gunakan context.Context untuk request dan database call.
Atur timeout pada setiap request untuk menghindari goroutine leaks.
8. Security & Best Practicesβ Input Validation & HashingGunakan bcrypt untuk hashing password.
Validasi input dengan go-playground/validator.
β Rate Limiting & Secrets ManagementGunakan golang.org/x/time/rate atau Redis untuk membatasi request.
Simpan credential di secrets manager (bukan di kode).
9. Efficient Goroutine & Worker Pool Managementβ Worker Pool & sync.PoolGunakan worker pool untuk task concurrent.
Gunakan sync.Pool untuk mengelola objek yang sering dialokasikan ulang.
10. Graceful Shutdownβ Handling SIGINT/SIGTERMPastikan aplikasi menangani SIGINT/SIGTERM untuk shutdown yang bersih.
Tutup semua koneksi database, cache, dan WebSocket saat aplikasi berhenti.
11. Modul & Package Organizationβ Domain-Driven Design (DDD) & Separation of ConcernsPisahkan kode ke dalam layer seperti repository, service, handler agar lebih maintainable.
12. CI/CD & Deploymentβ GitHub Actions / GitLab CIGunakan CI/CD pipeline untuk otomatisasi testing dan deployment.
Pastikan ada health check endpoint untuk monitoring di production π₯
Database Documentation = https://dbdocs.io/?utm_source=dbdocs
Migration DB = https://github.com/golang-migrate/migrate
Last updated