a.
mcp.altay.socialMCP & Prompt Katalogu
Rules
·v1.0.0·2026-04-22

Go Projesi Kuralları

Modern Go (1.22+) projeleri için kural seti — paket yapısı, error handling, concurrency pattern'leri, context kullanımı, test disiplini, go vet + golangci-lint baseline. CLAUDE.md / .cursorrules için.

gogolangbackendconcurrencyrulesclaude-md

İçerik

Bu içeriği projenin CLAUDE.md / AGENTS.md / .cursorrules dosyasına yapıştır.


Go Projesi Kuralları

Version & tooling

  • Go 1.22+ (generics, range-over-func, improved slog).
  • go mod tidy commit öncesi zorunlu.
  • go.mod ve go.sum commit edilir.
  • Replace directive CI'da yasak (local dev için geçici kabul, commit'ten önce kaldır).
  • Formatter: gofmt / goimports (pre-commit).
  • Linter: golangci-lint. Aktif linter'lar:
    linters:
      enable:
        - errcheck     # yakalanmayan error'lar
        - govet
        - gosec        # security
        - revive       # style (golint yerine)
        - staticcheck
        - unused
        - ineffassign
        - gocritic
        - bodyclose    # HTTP body kapatılmadı mı?
        - contextcheck # context propagation
        - errorlint    # fmt.Errorf + %w
        - gocyclo
        - exhaustive   # switch exhaustive?
        - sqlclosecheck
    

Paket yapısı

  • Layout: cmd/, internal/, pkg/ (opsiyonel).
    myapp/
      cmd/
        server/main.go       // binary entry
        migrate/main.go
      internal/               // export edilmez, private
        api/
        service/
        repository/
      pkg/                    // diğer projelerle paylaşılacaksa
      go.mod
    
  • internal/ kurulum tercih — sızıntıyı derleyici engeller.
  • pkg/ sadece gerçekten public API için (library dışa açıyorsan).
  • Paket adı: kısa, snake_case değil lowercase, tek kelime tercih: user, payment, storage.
  • util, common, helpers paketleri yasak — anlamsız gruplama.

Error handling

  • Error döndüren fonksiyonda error kontrol:
    ✅ result, err := doThing()
       if err != nil {
         return fmt.Errorf("doThing: %w", err)
       }
    
    ❌ result, _ := doThing()  // yasak (golangci-lint errcheck yakalar)
    
  • Error wrapping: fmt.Errorf("context: %w", err). Mesaj + wrap, user-facing detay ayrı.
  • Sentinel error'lar:
    var ErrNotFound = errors.New("not found")
    // kullanım:
    if errors.Is(err, ErrNotFound) { ... }
    
  • Custom error type'lar yapısal data gerekirse:
    type ValidationError struct {
      Field   string
      Message string
    }
    func (e *ValidationError) Error() string { ... }
    // kullanım:
    var ve *ValidationError
    if errors.As(err, &ve) { ... }
    
  • Panic yasak production kodda — sadece gerçekten unrecoverable (init failure) durumda.
  • recover() goroutine panic'i için — ayrıca log + metric.

Context

  • Her I/O fonksiyonu ctx context.Context alır, ilk parametre:
    func (s *Service) GetUser(ctx context.Context, id UserID) (*User, error)
    
  • context.Background() sadece main'de (veya long-running background job'ın kökünde).
  • context.TODO() geçici — refactor PR'ında gerçek context'e çevrilir.
  • Cancel'ı unutma:
    ctx, cancel := context.WithTimeout(parent, 5*time.Second)
    defer cancel()
    
  • context.WithValue minimal kullan — tracing, request ID, auth user gibi cross-cutting.

Concurrency

  • Goroutine'ı başlatan, sonlandırmasını da düşünür. Fire-and-forget yasak:
    ❌ go doWork()
    ✅ go func() {
         defer wg.Done()
         if err := doWork(ctx); err != nil { ... }
       }()
    
  • Wait group veya errgroup.Group çoklu goroutine için.
  • Channel direction: chan<-, <-chan — unutma, dokümantasyon.
  • Mutex: zero value kullanılabilir (var mu sync.Mutex), pointer yapma.
  • Atomic basit counter için (atomic.Int64).
  • sync.Map sadece spesifik case'ler için — çoğu zaman map + RWMutex daha iyi.
  • Data race: go test -race CI'da zorunlu.
  • Channel'i sender kapatır (receiver değil). "Who owns the channel" net.

Slice / map nuance

  • Slice append kopyası:
    a := []int{1,2,3}
    b := append(a, 4)
    // a ve b paylaşılabilir — dikkat
    
  • Slice capacity hint:
    s := make([]int, 0, 100)  // capacity pre-allocated
    
  • Map concurrent access yasak. Read-only için bile sync.RWMutex veya sync.Map.
  • nil slice vs boş slice: API contract'ta belirt — genelde return nil kabul, len() == 0 check.

Logging

  • log/slog (Go 1.21+) — structured. log package yasak.
  • Handler seçimi: JSON production, Text dev.
  • Logger propagation: context içinde veya explicit parameter.
  • Seviyeler: Debug, Info, Warn, Error.
  • log.Fatal yasak (defer çalıştırmaz, exit code 1). Yerine os.Exit(1) after graceful cleanup.
logger.Info("order created", "order_id", orderID, "user_id", userID)

HTTP handler'lar

  • http.Handler interface preferred:
    func (h *OrderHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { ... }
    
  • Middleware pattern:
    mux.Handle("/orders", authMiddleware(rateLimitMiddleware(orderHandler)))
    
  • Body close edilir: defer r.Body.Close() (body'yi okuyorsan).
  • Response header status'tan önce yazılır.
  • Timeout'lar: http.Server{ReadTimeout, WriteTimeout, IdleTimeout} — her zaman set.
  • http.DefaultServeMux yasak — explicit http.NewServeMux().

Database

  • database/sql veya ORM (sqlc, Ent, GORM). sqlc (code generation) tercih edilir — raw SQL + type safety.
  • Connection pool config:
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(5)
    db.SetConnMaxLifetime(5 * time.Minute)
    
  • Rows.Close() defer edilir.
  • Prepared statement prod'da cache'li.
  • context.Context query'ye geçerQueryContext, ExecContext.

Testing

  • Test dosyası: *_test.go, aynı paket içinde.
  • Table-driven test:
    tests := []struct{
      name    string
      input   string
      want    int
      wantErr bool
    }{
      {"empty", "", 0, false},
      ...
    }
    for _, tt := range tests {
      t.Run(tt.name, func(t *testing.T) { ... })
    }
    
  • testify popüler ama tercih edilmez ileri projede (stdlib + helper yeterli). Kullanılıyorsa require vs assert ayrımına dikkat.
  • t.Cleanup teardown için.
  • t.Parallel() bağımsız testler için.
  • Benchmark: BenchmarkX. Performance iddia ediliyorsa destekleyen benchmark.
  • Fuzz test Go 1.18+ — input parsing / serialization için.
  • httptest.NewServer HTTP handler test.

Struct & interface

  • Struct field'lar exported ise dokümantasyon zorunlu:
    // User represents a registered account.
    type User struct {
      // ID is a UUID v7 string.
      ID string
    }
    
  • Interface tanımı consumer tarafında, provider'da değil — "accept interfaces, return concrete types".
  • Küçük interfaceio.Reader, io.Writer örnek. 5+ method = yeniden düşün.
  • Embedding inheritance değil composition.
  • Pointer vs value receiver: tutarlı (bir tipte karıştırma). Büyük struct / mutation varsa pointer.

Build & deployment

  • Build:
    go build -ldflags="-w -s -X main.version=$(git rev-parse HEAD)" ./cmd/server
    
  • Static binary (CGO_ENABLED=0) — Docker'da scratch / distroless.
  • Multi-stage Dockerfile golden.
  • Reproducible build: GOFLAGS="-trimpath", locked toolchain.

Performance pragmatiği

  • -race test devamlı açık (performance cost ama production'da değil).
  • Profile önce optimize: pprof CPU/memory.
  • Allocation sayısı: hot path'te azaltmak için sync.Pool, buffer reuse.
  • strings.Builder string concat loop'ta.
  • bytes.Buffer binary concat için.
  • Benchmark'lı iddia — "bu daha hızlı" demeden ölç.

Secret & config

  • os.Getenv + zod-benzeri validation yerine envconfig kütüphanesi.
  • Viper karmaşık config hierarchy için.
  • Hardcoded secret yasak.
  • TLS config MinVersion: tls.VersionTLS12.

Yasak listesi (özet)

  • _, err := ...; _ (error ignore)
  • panic() production kodda
  • log.Fatal (defer atlatır)
  • log package (use log/slog)
  • Goroutine'ı wait group'sız başlatmak
  • Context'siz I/O fonksiyon
  • Global state (package-level var mutable) gereksiz yere
  • util, helpers, common paket adı
  • Interface tanımı 5+ method
  • Channel'i sender dışında kapatmak
  • Mutex'i embedding ile export etmek (Lock/Unlock public olur)
  • Struct'a JSON tag eksik (field leak veya case mismatch)
  • init() çok iş yapan (test yan etkileri)
  • interface{} / any gerçekten gerekli olmadıkça

Commit

Conventional Commits. Kapsam: api, cmd, db, worker, infra.