
Mon Aug 17 2026

Merhaba! 👋
Bu yazıda AI‑destekli kod yazma sürecini bir arada ele alıyoruz. Amacımız: prompt → kod → derleme hatası → düzeltme döngüsünün geliştirici deneyimini nasıl şekillendirdiğini görmek.
Neden önemli?
Go’nun rolü
Go, hızlı derleme ve net hata mesajları sayesinde bu döngüde öğrenme maliyetini en aza indirir.
LLM’ler (Copilot, Cursor, ChatGPT vb.) kod yazarken çok hızlı oluyorlar ama derleme / çalışma zamanında sık sık takılıyorlar 🤯.
Geliştirici olarak şu döngüye giriyoruz:
ModuleNotFoundError, Rust’ta use eksikliği&mut / & karıştırıyor# LLM ürettiği kod
def fetch_user(user_id: int) -> dict:
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json()
print(fetch_user(42))
Ne oldu?
requests import edilmedi → NameError404 dönerse response.json() ValueError fırlatır (tip garantisi yok)Küçük düzeltme ile çalışır hale getirmek:
import requests
from typing import Optional
def fetch_user(user_id: int) -> Optional[dict]:
response = requests.get(f"https://api.example.com/users/{user_id}")
if response.status_code != 200:
return None
return response.json()
Bu sayede import hatası giderildi ve hata durumunda
Nonedönüyoruz 👍
// LLM ürettiği kod
fn add_prefix(mut s: String, prefix: &str) -> String {
s.insert_str(0, prefix);
s
}
fn main() {
let name = String::from("Rust");
let with_prefix = add_prefix(name, "Lang: ");
println!("{}", name); // ❌ name moved!
}
Ne oldu?
add_prefix ownership alır (mut s: String) → name move olmuşname kullanmaya çalıştığımızda compile error: value borrowed here after move 🚫Düzeltme — referans alıp kopyalama yap:
fn add_prefix(s: &str, prefix: &str) -> String {
let mut owned = s.to_string();
owned.insert_str(0, prefix);
owned
}
fn main() {
let name = String::from("Rust");
let with_prefix = add_prefix(&name, "Lang: ");
println!("Orijinal: {}", name); // ✅ hala kullanılabilir
println!("Yeni: {}", with_prefix);
}
Nasıl çalışıyor?
Fonksiyon artık&stralır, ownership almıyor. İçerdeto_string()ile kendi sahipliğini oluşturuyor. Böylece caller’ınnamedeğişkeni move olmuyor ✅
| Sorun | Hızlı çözüm | Kalıcı alışkanlık |
|---|---|---|
| Eksik import | LLM’ye “import ekle” de | Kendi snippet’larını (ör. import requests) hazır tut |
| Tip uyumsuzluğu | Optional, Result ekle |
Type hint ve mypy / rust-analyzer ile CI’da kontrol et |
| Borrow checker | &str / &String kullan |
Ownership modelini öğren, LLM’den “referans al” iste |
Küçük bir pratik:
LLM’den kod isteyin, ilk derlemeyi siz yapın, hata mesajını kopyalayıp tekrar sorun. Ama her seferinde aynı hataları düzeltmek yerine, yukarıdaki tablo gibi bir “hata‑çözüm” notu tutun. Zamanla LLM de sizin tercihlerinizi öğrenir ve döngü kırılır 🚀
Hazırsan başlayalım 🚀
Go’yu tanıyan herkes bilir: “Hata bir değer, bir istisna değil.” Bu felsefe, LLM’in yazdığı kodun hemen derlenmesini ve hataların anında görünmesini sağlar.
error dönüşü → fonksiyon imzasında hata ihtimali bellidir, sürpriz yok.panic/recover yerine return err → kontrol akışı sıradan bir if bloğuyla yönetilir, stack trace karmaşası yok.func fetchUser(id int) (*User, error) {
// ... veri tabanı sorgusu ...
if !found {
return nil, fmt.Errorf("kullanıcı bulunamadı: %d", id)
}
return &User{ID: id, Name: "Ali"}, nil
}
func main() {
user, err := fetchUser(42)
if err != nil {
log.Printf("hata: %v", err)
return
}
fmt.Println("Kullanıcı:", user.Name)
}
Ne oluyor burada?
fetchUser hem veri hem de olası hata döndürür.main içinde if err != nil ile tek satırda hata yakalanır.Geçen hafta bir mikro servis için otomatik kod üreteci kullandım. Python’da try/except blokları unutulduğunda runtime’da şaşırtıcı hatalar alıyordum. Aynı işi Go’da denedim: LLM her fonksiyonda (data, error) döndürdü, ben de if err != nil yazdım. Derleme anında eksik hata kontrolleri uyarısı aldım, produzione çıkmadan önce düzeltim. ✅
return err yaklaşımı = hata akışını görünür ve test edilebilir kılar.Bu yüzden Go, özellikle LLM destekli geliştirme akışlarında güvenilir bir mitra olur. 🤝
Go’yu seçtiğim en büyük nedenlerden biri saniyeler içinde derleme hızı 🎯. Bir projeye go build dediğimde, coffee break bitmeden binary hazır. Bu, AI asistanıyla birlikte hızlı prototip döngüsünü inanılmaz kolaylaştırıyor: kod yaz → derle → test et → tekrar et, hepsi dakikalar içinde.
Bağımlılık yönetimi de go mod ile sıfır sürpriz. go mod tidy bir komutla eksik paketleri çeker, gereksizleri temizler. Versiyon çakışması yok, vendor klasörüyle uğraşma yok ✅.
Standart kütüphane zengin ve üretime hazır. net/http, encoding/json, context, log… hepsibuiltin. Üçüncü parti framework aramak zorunda kalmıyorsun ⛔.
package main
import (
"encoding/json"
"log"
"net/http"
)
type Mesaj struct {
Metin string `json:"metin"`
}
func main() {
http.HandleFunc("/api/mesaj", func(w http.ResponseWriter, r *http.Request) {
var m Mesaj
if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
http.Error(w, "Geçersiz JSON", http.StatusBadRequest)
return
}
yanit := map[string]string{"echo": m.Metin}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(yanit)
})
log.Println("Sunucu :8080 portunda dinleniyor 🚀")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Ne oluyor burada?
net/http ile bir endpoint açıyoruz.encoding/json ile gelen body’yi struct’a çözüp, yanıtı tekrar JSON olarak döndürüyoruz.go run main.go derhal çalışır.| Metrik | Go (stdlib) | Tipik Node/Express |
|---|---|---|
| Derleme süresi (10 k LOC) | ~1 s | – (yorumlu) |
| İlk istek gecikmesi (cold start) | <5 ms | 30‑50 ms |
| Bellek kullanımı (idle) | ~5 MB | ~30 MB |
Go’nun derleme hızı + hafif runtime = CI/CD pipeline’larında dakikalar kazanıyorsun. AI asistanıyla “şu endpointi ekle” dediğinde, saniyeler içinde derlenip test edilebilir kod üretiliyor 🔁.
Özetle:
Bu kombinasyon, AI destekli geliştirmede prototip → prod sürecini inanılmaz kısaltıyor. Hadi bir sonraki bölümde bu avantajları bir mikroservis şablonuna nasıl taşıyacağımızı görelim 🚀.
Hazırsan başlayalım! Benim en sevdiğim yöntem: aynı işi yapan üç kod bloğunu yan yana koyup, "ben denedim, şu oldu" demek 🎯 Bugün basit bir /hello REST endpoint'i üzerinden gideceğiz. Her dilde minimal, production-ready olmayan ama çalışan bir örnek.
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/hello")
def hello():
return jsonify({"message": "Merhaba Python!"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
Ne oluyor burada?
jsonify yazım yanlışı).use actix_web::{get, App, HttpResponse, HttpServer, Responder};
#[get("/hello")]
async fn hello() -> impl Responder {
HttpResponse::Ok().json(serde_json::json!({"message": "Merhaba Rust!"}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(hello))
.bind("0.0.0.0:8000")?
.run()
.await
}
Ne oluyor burada?
#[get], #[actix_web::main]) routing'i compile-time'da çözer.serde_json::json! makrosu compile-time type-check yapar — JSON bozuksa derleme hatası alırsın 🛠package main
import (
"encoding/json"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"message": "Merhaba Go!"})
}
func main() {
http.HandleFunc("/hello", helloHandler)
http.ListenAndServe(":8000", nil)
}
Ne oluyor burada?
net/http) yeterli — dependency yok, go mod init bile lazım değil (tek dosya go run main.go).500 döner ama panic etmez.| Kriter | 🐍 Python (Flask) | 🦀 Rust (Actix) | 🐹 Go (net/http) |
|---|---|---|---|
| Kod yazma süresi | ~15 sn | ~5 dk | ~2 dk |
| İlk derleme / başlatma | Anında (interpreted) | ~15-20 sn | ~300-500 ms |
| LLM doğruluk oranı | %99 | %85-90 | %95+ |
| Runtime hata riski | 🔴 Yüksek (type yok) | 🟢 Sıfır (compile-time) | 🟡 Düşük (runtime encode) |
| Debug süresi (tip hatası) | 5-30 dk (prod'da) | 0 dk (derlemede) | 1-2 dk (log ile) |
| Binary boyutu | N/A (venv + interpreter) | ~3-5 MB (release) | ~5-10 MB (static) |
| Cold start (container) | ~2-3 sn | ~50-100 ms | ~50-100 ms |
Hangisini seçeceksin? Proje bağlamına bak. Ben hepsini farklı repolarda tutuyorum — her biri kendi alanının kralı ⛔️👑
Hazırsan başlayalım! 🎯 Bu bölümde Cursor (veya GitHub Copilot) yardımıyla sıfırdan bir Go projesi nasıl ayağa kalkar, adım adım göreceğiz. Okuyup geçme — yanınızda bir terminal açın, benimle birlikte yazın. Mini bir workshop hissine kapılacaksınız 🛠
go mod init Çalıştırİlk iş: boş bir klasör, sonra modül başlatma.
mkdir go-ai-demo && cd go-ai-demo
go mod init github.com/kullanici/go-ai-demo
Ne oluyor burada?
go.mod dosyası oluşur, bağımlılık takibi başlar.Cursor'da Cmd+L (veya Copilot Chat) açıp şunu yazıyorum:
Prompt:
"Go'danet/httpkullanarak 8080 portunda dinleyen,/healthve/api/helloendpoint'li basit birmain.goyaz./health→{"status":"ok"}döndürsün,/api/hello→{"message":"Merhaba, Dünya!"}döndürsün. JSON response içinencoding/jsonkullan."
🤖 AI'nın ürettiği kod (ilk versiyon):
// main.go
package main
import (
"encoding/json"
"net/http"
)
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"message": "Merhaba, Dünya!"})
}
func main() {
http.HandleFunc("/health", healthHandler)
http.HandleFunc("/api/hello", helloHandler)
http.ListenAndServe(":8080", nil)
}
Bu sayede ne oluyor?
Kod temiz, derlenebilir durumda. Ama bir küçük detay kaçıyor: http.ListenAndServe hata döndürürse program sessizce çöker. Hadi bunu da düzelttirelim.
Prompt:
"mainfonksiyonundaListenAndServehatasını logla velog.Fatalile çık.logpaketini import et."
🤖 AI'nın güncellediği kod:
// main.go
package main
import (
"encoding/json"
"log"
"net/http"
)
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"message": "Merhaba, Dünya!"})
}
func main() {
http.HandleFunc("/health", healthHandler)
http.HandleFunc("/api/hello", helloHandler)
log.Println("Server 8080 portunda başlatılıyor...")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatalf("Server hatası: %v", err)
}
}
Terminalde:
go run main.go
Beklenen çıktı:
2024/01/15 14:32:10 Server 8080 portunda başlatılıyor...
Şimdi ayrı bir terminalde test edelim:
curl http://localhost:8080/health
# {"status":"ok"}
curl http://localhost:8080/api/hello
# {"message":"Merhaba, Dünya!"}
✅ Çalışıyor!
Eğer 8080 portu doluysa:
2024/01/15 14:35:22 Server hatası: listen tcp :8080: bind: address already in use
exit status 1
Çözüm: Ya portu değiştirin (:8081), ya da işgal eden süreci杀掉 (kill) edin:
lsof -ti:8080 | xargs kill -9
# veya
go run main.go # farklı port için: PORT=8081 go run main.go (kodda os.Getenv("PORT") okuması gerekir)
💡 İpucu: AI'a şunu sorun: "Portu environment variable'dan okuyan, default 8080 olan versiyon yaz" — pratik olur.
go build ile Binary Alalım 📦go build -o go-ai-demo .
./go-ai-demo
Artık dağıtılabilir tek bir binary'niz var. Dockerize etmek isterseniz Dockerfile için de AI'dan yardım alabilirsiniz — ama o ayrı bir bölüm 😉
| Adım | Ne Oldu? |
|---|---|
| 1 | go mod init ile modül başlattık |
| 2 | AI'dan HTTP server iskeleti istedik |
| 3 | Hata yönetimi + log eklettik (iteratif prompt) |
| 4 | go run ile test ettik, curl ile doğruladık |
| 5 | Port hatası simüle edip çözüm gördük |
| 6 | go build ile binary çıktısı aldık |
Hadi şimdi siz deneyin! Kendi endpoint'inizi ekleyin, middleware yazdırın, test dosyası isteyin... 🎉
Sonraki bölümde bu projeyi Dockerize edip, CI/CD pipeline'ına sokacağız. Görüşmek üzere! 👋
Arkadaşlar, konuyu özetlersek Go’nun AI destekli geliştirmeyle neden bu kadar iyi oturduğunu şu maddelerle toparlayabiliriz:
if err != nil yazmak sıkıcı gelebilir ama AI bu pattern’i mükemmel tanıyor. Hata yakalama, loglama, yeniden deneme kodlarını saniyeler içinde üretebiliyor.go build saniyeler sürüyor. AI ile yazdığımız kodu hemen test edip iterasyona giriyoruz. Bekleme yok, akış kopmuyor.Kısacası: Go, AI’nin “anladığı” en az sürprizli, en hızlı döndüren dil.
Hadi bir sonraki projenizde Go deneyin, farkı hissedeceksiniz ✨
Hazırsan başlayalım 🚀 — şu küçük alışkanlıklar, AI destekli Go geliştirmenizi ciddi oranda hızlandırır.
go generate ile kod üretimini otomatikleştirgo generate ./... çalıştırın.//go:generate mockgen -source=service.go -destination=mock_service.go -package=mypkg
type Service interface {
DoSomething(ctx context.Context) error
}
Bu sayede
mock_service.goher değişiklikte otomatik güncellenir ✨
golangci-lint ile statik analizi CI’ye entegre edinerrcheck, govet, staticcheck, gofmt, gosec + AI kodunda sık görülen ineffassign, unused..golangci.yml):run:
timeout: 3m
issues-exit-code: 1
linters:
enable:
- errcheck
- govet
- staticcheck
- gofmt
- gosec
- ineffassign
- unused
disable-all: true
linters-settings:
govet:
enable-all: true
staticcheck:
checks: ["all", "-ST1000"]
issues:
exclude-rules:
- path: _test\.go
linters:
- gosec
golangci-lint run ./... (CI pipeline’ınıza ekleyin) ✅.vscode/settings.json){
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"],
"go.formatTool": "goimports",
"go.testFlags": ["-v", "-race"],
"go.coverOnSave": true,
"editor.formatOnSave": true,
"[go]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
}
Takım arkadaşlarınız
git pullyaptıktan hemen sonra aynı deneyimi yaşar 🤝
.github/copilot-instructions.md veya .cursor/rules/)_test.go suffix’iyle, table-driven pattern kullanarak yazılmalı.”“Go 1.22, clean architecture, hata yönetimi
fmt.Errorf(... %w)pattern’iyle.”
Bu dosyaları repo’ya koyduğunuzda her AI asistanı aynı standartları takip eder 🎯
testify/require + mockgen| Adım | Ne Yapmalı? |
|---|---|
| 1️⃣ | Her public fonksiyon için en az bir happy-path + bir error-case |
| 2️⃣ | testify/require ile require.NoError(t, err) — okunurluk artar |
| 3️⃣ | Mock’ları go generate ile üretin, elle yazmayın |
| 4️⃣ | go test -race -coverprofile=coverage.out ./... — race detector zorunlu ⚡ |
| 5️⃣ | Coverage %80+ hedefleyin, ama kalite > miktar |
go generate + golangci-lint = manuel hata sıfır 🛠Hadi bu ayarları repo’nuza ekleyin, sonra AI asistanınızla “yeni bir handler yaz” diyin — farkı hemen hissedeceksiniz 😉
Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.
All rights reserved