Clean Architecture: Go Projelerinde Klasör Yapısı Nasıl Olmalı?

  • Konbuyu başlatan Konbuyu başlatan irfo
  • Başlangıç tarihi Başlangıç tarihi

irfo

Moderatör
Top Poster Of Month
Katılım
7 Ocak 2026
Mesajlar
290
Tepkime puanı
2
Puanları
18

"Dosyalarımı Nereye Koyayım?"​

Go, Python (Django) veya Java (Spring) gibi katı bir klasör yapısı dayatmaz. main.go oluşturup her şeyi içine yazabilirsiniz. Ancak proje büyüdükçe bu bir kabusa dönüşür.Topluluk tarafından kabul görmüş (resmi olmayan ama fiili standart olan) "Standard Go Project Layout" yapısını inceleyelim.

Önerilen Klasör Yapısı​

  1. /cmd: Giriş Kapısı.
    • Uygulamanızın çalıştırılabilir (main) dosyaları buradadır.
    • Örn: /cmd/api/main.go, /cmd/worker/main.go.
    • Kural: Burada iş mantığı (business logic) olmamalıdır. Sadece başlatma kodları yer alır.
  2. /internal: Özel Kodlar (Kritik!).
    • Go derleyicisi bu klasöre özel davranır. /internal içindeki kodları, başka projeler import edemez.
    • Projenizin kalbi, iş mantığı, veritabanı modelleri burada durur. Dışarıya kapalıdır, güvenlidir.
  3. /pkg: Genel Kütüphaneler.
    • Başka projelerin de kullanabileceği (import edebileceği) yardımcı kodlar (örn: tarih formatlayıcı, validasyon araçları) buraya konur.
  4. /api: Kontratlar.
    • OpenAPI (Swagger) dosyaları, gRPC .proto dosyaları.

Katmanlı Mimari (Clean Architecture) Örneği​

Kodun bağımlılığı her zaman İçeriye Doğru olmalıdır.

  • Handler (Transport Layer): HTTP isteklerini karşılar (internal/handler).
  • Service (Business Layer): İş kurallarını uygular (internal/service).
  • Repository (Data Layer): Veritabanı ile konuşur (internal/repository).
Örnek Akış:main.go -> Handler çağırır -> Service çağırır -> Repository çağırır.

Kod:
// internal/repository/user_repo.gofunc (r *UserRepository) GetByID(id int) (*User, error) { ... }

// internal/service/user_service.go// Service, Repository'e bağımlıdır (Interface üzerinden olması en iyisidir)func (s *UserService) FindUser(id int) (*User, error) {// İş kuralı: ID negatif olamazif id < 0 { return nil, errors.New("geçersiz id") }return s.repo.GetByID(id)}

Sonuç​

Bu yapı başlangıçta "fazla mühendislik" (over-engineering) gibi gelebilir. Ancak projeniz 50 dosyayı geçtiğinde, /internal kullanımı ve katmanlı yapı hayatınızı kurtarır. Spagetti koddan kaçınmanın yolu budur.
 
Geri
Üst