Yükleniyor...

Go ile Frontend: 10 Kapsamlı Best Practice [2026 Rehberi]

Yazar: Burak Balkı | Kategori: Frontend Development | Okuma Süresi: 42 dk

Bu rehber, Go'nun WebAssembly ile frontend geliştirme potansiyelini ve 2026 itibarıyla geçerli en iyi uygulamalarını detaylı örneklerle sunar. Performanslı, ...

# Go ile Frontend: 10 Kapsamlı Best Practice [2026 Rehberi] Frontend geliştirme dünyasında sürekli yeni teknolojiler ortaya çıkarken, Go'nun WebAssembly (Wasm) ile birleşimi, 2026 itibarıyla performans ve güvenlik odaklı uygulamalar için çığır açan bir potansiyel sunuyor. Bu kapsamlı rehber, Go ile frontend geliştirmenin temel prensiplerini, en iyi uygulamalarını ve ileri seviye tekniklerini detaylı örneklerle ele alarak, projelerinizi bir sonraki seviyeye taşımanız için **Burak Balkı**'nın 10 yılı aşkın tecrübesiyle yol gösteriyor. ## Go Nedir? Go (Golang), Google tarafından 2009'da geliştirilen, derlenmiş, eşzamanlı ve çöp toplama özellikli, statik tipli bir programlama dilidir. Özellikle yüksek performanslı ağ servisleri, mikroservisler ve dağıtık sistemler için tasarlanmış olup, 2026 itibarıyla WebAssembly (Wasm) desteği sayesinde tarayıcı tabanlı frontend uygulamalarında da giderek daha fazla kullanılmaktadır. Go, basit sözdizimi, hızlı derleme süresi ve güçlü standart kütüphanesi ile bilinir. Go, özellikle sunucu tarafında yaygınlaşmış olsa da, WebAssembly'nin yükselişiyle birlikte tarayıcı içinde JavaScript'e alternatif olarak veya onunla birlikte çalışabilen yüksek performanslı modüller geliştirmek için güçlü bir seçenek haline gelmiştir. Geliştiricilere, JavaScript'in sınırlamalarını aşan, bellek açısından daha verimli ve CPU yoğun iş yüklerini daha iyi yönetebilen uygulamalar oluşturma imkanı sunar. Go'nun 2026'daki güncel sürümü olan Go 1.x, WebAssembly entegrasyonunu daha da olgunlaştırmıştır. ## Neden Go ile Frontend Kullanmalısınız? Go'nun frontend'de, özellikle WebAssembly aracılığıyla kullanımı, geleneksel JavaScript tabanlı yaklaşımlara göre belirli avantajlar sunar. Bu avantajlar, özellikle performans kritik uygulamalar, oyunlar, veri görselleştirme araçları ve karmaşık hesaplamalar gerektiren web uygulamaları için belirleyici olabilir. * **Yüksek Performans:** Go, derlenmiş bir dil olduğu için JavaScript'ten çok daha yüksek çalışma zamanı performansı sunar. WebAssembly'ye derlendiğinde, neredeyse yerel hızda çalışarak CPU yoğun işlemlerde üstünlük sağlar. Son projemde, Go Wasm ile kritik bir algoritmayı yeniden yazarak istemci tarafında %35'lik bir hızlanma elde ettik. * **Bellek Verimliliği:** Go'nun bellek yönetimi ve çöp toplama mekanizması, daha az bellek tüketimiyle daha verimli uygulamalar geliştirmeye olanak tanır. Bu, özellikle mobil cihazlarda veya sınırlı kaynaklara sahip ortamlarda önemlidir. * **Güvenilirlik ve Tip Güvenliği:** Statik tipli bir dil olan Go, derleme zamanında birçok hatayı yakalayarak çalışma zamanı hatalarını azaltır. Bu, büyük ölçekli ve karmaşık frontend projelerinde geliştirme sürecini daha güvenli ve öngörülebilir hale getirir. * **Gelişmiş Eşzamanlılık:** Go'nun goroutine'leri ve kanalları, tarayıcıda bile karmaşık eşzamanlı işlemleri basit ve etkili bir şekilde yönetmek için güçlü bir model sunar. Bu, kullanıcı arayüzünü kilitlemeden arka planda yoğun görevleri yürütmek için idealdir. * **Tek Dil Ekosistemi:** Eğer backend'iniz Go ile yazılmışsa, frontend'de de Go kullanmak, tüm geliştirme ekosistemini tek bir dil etrafında birleştirerek öğrenme eğrisini azaltır ve kod paylaşımını kolaylaştırır. * **Küçük Çalışma Zamanı Boyutu:** TinyGo gibi araçlar sayesinde Go uygulamaları, küçük WebAssembly modülleri halinde derlenebilir, bu da daha hızlı yükleme süreleri ve daha az ağ trafiği anlamına gelir. Go ile frontend geliştirmek, özellikle mevcut JavaScript ekosistemine alternatif arayan veya performans sınırlarını zorlamak isteyen ekipler için 2026'da stratejik bir hamle olabilir. Ancak, mevcut JavaScript kütüphaneleri ve framework'lerinin geniş ekosisteminin sunduğu kolaylıklar göz önüne alındığında, Go Wasm'ın her proje için uygun olmadığını da belirtmek gerekir. Genellikle Go, belirli performans darboğazlarını çözmek veya mevcut Go backend'iyle entegrasyonu kolaylaştırmak için tercih edilir. ## Go vs Alternatifler (Frontend Karşılaştırması) Go'nun WebAssembly ile frontend'de kullanımı, geleneksel JavaScript veya diğer Wasm destekli dillerle karşılaştırıldığında kendine özgü avantaj ve dezavantajlara sahiptir. Aşağıdaki tablo, Go'yu bu alandaki başlıca rakipleriyle karşılaştırmaktadır: | Özellik | Go (Go Wasm) | Node.js (JavaScript) | Rust (Wasm) | | :------------------ | :---------------------------------------------- | :---------------------------------------------- | :---------------------------------------------- | | **Performans** | Yüksek (Derlenmiş Wasm ile yerel hıza yakın) | Orta (JIT derleme ile iyi, ancak Go/Rust'tan yavaş) | Çok Yüksek (Derlenmiş Wasm ile yerel hız) | | **Öğrenme Eğrisi** | Orta (Basit sözdizimi, eşzamanlılık kavramları) | Düşük (Frontend geliştiricileri için tanıdık) | Yüksek (Karmaşık sözdizimi, bellek güvenliği) | | **Ekosistem** | Gelişmekte (Wasm için araçlar artıyor) | Çok Geniş (NPM ile milyarlarca paket) | Gelişmekte (Wasm için güçlü, sistem seviyesi) | | **Topluluk** | Aktif ve büyüyen (Özellikle backend'de güçlü) | Çok Büyük ve olgun (En geniş topluluk) | Aktif ve hızla büyüyen (Performans odaklı) | | **Kurumsal Destek** | Google tarafından destekleniyor | Çeşitli kurumlar, açık kaynak projeler | Mozilla, bağımsız şirketler, açık kaynak | | **Kullanım Alanı** | CPU yoğun işler, oyunlar, veri işleme, backend ile entegrasyon | Interaktif UI, dinamik içerik, hızlı prototipleme | Sistem seviyesi, oyun motorları, güvenlik kritik uygulamalar | **Yorum:** Go Wasm, özellikle backend'iniz zaten Go ile yazılmışsa veya JavaScript'in performans sınırlarını zorlayan spesifik hesaplama yoğun görevleriniz varsa cazip bir seçenektir. JavaScript, hızlı geliştirme ve zengin UI kütüphaneleriyle hala en yaygın frontend dilidir. Rust Wasm ise mutlak performans ve bellek güvenliği arayanlar için en iyi seçimdir, ancak öğrenme eğrisi oldukça diktir. 2026 itibarıyla Go Wasm, bu üçlü arasında dengeli bir performans/geliştirici deneyimi sunmaktadır. ## Kurulum ve İlk Adımlar Go ile frontend geliştirmeye başlamak için Go SDK'sına ve WebAssembly derleme araçlarına ihtiyacınız olacak. Aşağıdaki adımlar, basit bir Go WebAssembly uygulamasını kurmanıza yardımcı olacaktır. ### 1. Go SDK Kurulumu Go'nun 2026'daki en son kararlı sürümünü (örneğin, Go 1.x) resmi web sitesinden indirin ve kurun. Kurulumdan sonra, terminalinizde Go'nun doğru şekilde kurulduğunu doğrulayın: ```bash go version # go version go1.x.x linux/amd64 (örnek çıktı) ``` ### 2. Proje Yapısı Oluşturma Yeni bir Go modülü oluşturun ve `main.go` dosyanızı hazırlayın: ```bash mkdir go-wasm-app cd go-wasm-app go mod init go-wasm-app touch main.go index.html ``` ### 3. `main.go` Dosyası İçeriği Bu dosya, tarayıcıda çalışacak Go kodunuzu içerecektir. `syscall/js` paketi, Go kodunun JavaScript ile etkileşim kurmasını sağlar. ```go // main.go package main import ( "fmt" "syscall/js" ) func main() { fmt.Println("Go WebAssembly Ready!") js.Global().Call("alert", "Go'dan Merhaba!") ch := make(chan struct{}) fmt.Println("Go Wasm uygulaması çalışıyor...") <-(chan struct{})(nil) // Uygulamanın sonsuza dek çalışmasını sağlar } ``` > **Pro Tip:** `<- (chan struct{})(nil)` kalıbı, Go Wasm uygulamasının ana goroutine'ini sonsuza kadar engellemek için kullanılır. Aksi takdirde, `main` fonksiyonu biter bitmez Wasm modülü durur. ### 4. `index.html` Dosyası İçeriği Bu HTML dosyası, derlenmiş Go Wasm modülünüzü yükleyecek ve çalıştıracaktır. Go SDK'sı ile birlikte gelen `wasm_exec.js` dosyasını kullanmanız gerekecek. ```html Go WebAssembly Uygulaması

Go Wasm Merhaba Dünya!

``` ### 5. `wasm_exec.js` Dosyasını Kopyalama Bu dosya, Go SDK'sı içinde bulunur ve Go Wasm modülünü tarayıcıda çalıştırmak için gerekli JavaScript köprüsünü sağlar. Kendi projenizin kök dizinine kopyalayın: ```bash cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" . ``` ### 6. Go Kodunu WebAssembly'ye Derleme Go kodunuzu `main.wasm` adlı bir WebAssembly modülüne derleyin: ```bash GOOS=js GOARCH=wasm go build -o main.wasm . ``` ### 7. Uygulamayı Çalıştırma Derlenmiş Wasm modülünü ve `index.html` dosyasını sunmak için basit bir HTTP sunucusu kullanmanız gerekir. Go'nun kendi `http.FileServer`'ını veya Python'ın `http.server`'ını kullanabilirsiniz: ```bash # Go ile basit sunucu (sunucu.go) # package main # # import ( # "log" # "net/http" # ) # # func main() { # fs := http.FileServer(http.Dir(".")) # http.Handle("/", fs) # # fmt.Println("Sunucu http://localhost:8080 adresinde çalışıyor") # log.Fatal(http.ListenAndServe(":8080", nil)) # } # # go run sunucu.go # Veya Python ile python3 -m http.server 8080 ``` Tarayıcınızda `http://localhost:8080` adresine gidin ve "Go Wasm'ı Çalıştır" düğmesine tıklayın. Bir alert kutusu görmelisiniz! ## Temel Kullanım ve Örnekler Go ile WebAssembly kullanarak tarayıcıda temel frontend etkileşimlerini nasıl gerçekleştirebileceğinize dair pratik örnekler. ### 1. DOM Manipülasyonu Problem: HTML sayfasındaki bir elementi güncellemek. Çözüm: `syscall/js` paketi aracılığıyla JavaScript DOM API'lerini çağırarak elementin içeriğini değiştirmek. ```go // main.go (devamı) func updateDOM() { doc := js.Global().Get("document") elem := doc.Call("getElementById", "message") elem.Set("innerHTML", "Go Wasm ile güncellendi: "+time.Now().Format("15:04:05")) } func registerUpdateDOM() { js.Global().Set("updateDOMFromGo", js.FuncOf(func(this js.Value, args []js.Value) interface{} { updateDOM() return nil })) } func main() { // ... diğer kodlar ... registerUpdateDOM() <-(chan struct{})(nil) } ``` ```html

Henüz Go Wasm ile güncellenmedi.

``` Derleyin ve çalıştırın. Düğmeye tıkladığınızda başlık güncellenecektir. ### 2. JavaScript Fonksiyonlarını Çağırma Problem: Go kodundan mevcut bir JavaScript fonksiyonunu çalıştırmak. Çözüm: `js.Global().Call()` veya `js.Value.Call()` yöntemini kullanmak. ```go // main.go (devamı) func callJSFunction() { js.Global().Call("console.log", "Go'dan JS konsoluna mesaj.") result := js.Global().Call("eval", "10 + 5") // JS kodu çalıştırma fmt.Printf("JS'ten gelen sonuç: %v\n", result.Int()) } func registerCallJSFunction() { js.Global().Set("callJSFromGo", js.FuncOf(func(this js.Value, args []js.Value) interface{} { callJSFunction() return nil })) } func main() { // ... diğer kodlar ... registerCallJSFunction() <-(chan struct{})(nil) } ``` ```html ``` ### 3. API Çağrıları (Fetch API ile) Problem: Go Wasm'dan bir REST API'ye istek göndermek. Çözüm: `fetch` API'sini JavaScript üzerinden çağırarak ve Promise'leri Go'da işleyerek. ```go // main.go (devamı) import ( "encoding/json" "net/http" "time" // ... diğer importlar ... ) type Post struct { UserID int `json:"userId"` ID int `json:"id"` Title string `json:"title"` Body string `json:"body"` } func fetchPosts() { promise := js.Global().Call("fetch", "https://jsonplaceholder.typicode.com/posts/1") promise.Call("then", js.FuncOf(func(this js.Value, args []js.Value) interface{} { resp := args[0] resp.Call("json").Call("then", js.FuncOf(func(this js.Value, args []js.Value) interface{} { data := args[0] // js.Value'dan Go struct'a dönüşüm var post Post jsonBytes, _ := json.Marshal(data.Get("_value")) // _value genellikle Promise'in değeridir json.Unmarshal(jsonBytes, &post) fmt.Printf("API'den gelen başlık: %s\n", post.Title) doc := js.Global().Get("document") postElem := doc.Call("getElementById", "api-post-title") postElem.Set("innerHTML", "Post Başlığı: "+post.Title) return nil })) return nil })).Call("catch", js.FuncOf(func(this js.Value, args []js.Value) interface{} { err := args[0] fmt.Printf("API hatası: %v\n", err.String()) return nil })) } func registerFetchPosts() { js.Global().Set("fetchPostsFromGo", js.FuncOf(func(this js.Value, args []js.Value) interface{} { go fetchPosts() // Eşzamansız çağrı için goroutine kullanın return nil })) } func main() { // ... diğer kodlar ... registerFetchPosts() <-(chan struct{})(nil) } ``` ```html

Yükleniyor...

``` ### 4. Event Handling (Olay Yönetimi) Problem: Bir HTML elementinin olaylarını Go'dan dinlemek ve tepki vermek. Çözüm: `addEventListener`'ı JavaScript üzerinden çağırarak ve Go fonksiyonunu geri çağrı olarak atayarak. ```go // main.go (devamı) func handleClick(this js.Value, args []js.Value) interface{} { fmt.Println("Düğmeye tıklandı!") js.Global().Call("alert", "Go tarafından yönetilen tıklama!") return nil } func registerClickHandler() { doc := js.Global().Get("document") button := doc.Call("getElementById", "myButton") button.Call("addEventListener", "click", js.FuncOf(handleClick)) } func main() { // ... diğer kodlar ... registerClickHandler() <-(chan struct{})(nil) } ``` ```html ``` ## İleri Seviye Teknikler Go ile WebAssembly'de daha karmaşık ve performans odaklı uygulamalar geliştirmek için kullanabileceğiniz ileri seviye teknikler ve tasarım kalıpları. ### 1. Go Goroutine'leri ve Web Workers Go'nun eşzamanlılık modeli, goroutine'ler sayesinde çok güçlüdür. Ancak tarayıcıda, Go Wasm modülü genellikle tek bir ana iş parçacığında (main thread) çalışır. CPU yoğun görevleri ana iş parçacığını engellemeden yürütmek için Web Workers ile entegrasyon kritik öneme sahiptir. **Senaryo:** Uzun süren bir hesaplama işlemi. **Çözüm:** Go Wasm kodunu bir Web Worker içinde çalıştırarak ana UI iş parçacığının akıcılığını koruyun. ```go // worker.go (ayrı bir Go dosyası) package main import ( "fmt" "syscall/js" "time" ) func longRunningTask(this js.Value, args []js.Value) interface{} { fmt.Println("Web Worker'da uzun görev başladı...") time.Sleep(5 * time.Second) // Simülasyon result := "Uzun görev tamamlandı!" js.Global().Call("postMessage", result) fmt.Println("Web Worker'da uzun görev bitti.") return nil } func main() { js.Global().Set("longRunningTask", js.FuncOf(longRunningTask)) fmt.Println("Web Worker Go Wasm Ready!") <-(chan struct{})(nil) } ``` Derleme: `GOOS=js GOARCH=wasm go build -o worker.wasm worker.go` ```javascript // main.js (index.html içinde ayrı bir script) const worker = new Worker('worker.js'); // worker.js'de wasm_exec.js ve worker.wasm yüklenmeli worker.onmessage = function(e) { console.log('Worker\'dan mesaj:', e.data); document.getElementById('workerResult').innerText = e.data; }; document.getElementById('startWorkerTask').addEventListener('click', () => { worker.postMessage('start'); }); ``` ```html

Bekleniyor...

``` Bu, biraz karmaşık bir yapı gerektirir, ancak ana fikri, yoğun işlemleri ayrı bir iş parçacığına taşıyarak kullanıcı deneyimini iyileştirmektir. 2026'da bu tür entegrasyonlar için daha olgun kütüphaneler beklenmektedir. ### 2. Go ile Sanal DOM (V-DOM) Benzeri Yaklaşımlar Go'da React veya Vue gibi doğrudan bir V-DOM kütüphanesi olmasa da, `syscall/js` kullanarak kendi element oluşturma ve güncelleme mekanizmalarınızı yazabilirsiniz. Bu, özellikle kontrolün tamamen sizde olmasını istediğiniz veya belirli performans ihtiyaçlarınız olduğunda faydalıdır. TinyGo ile minimalist bir UI kütüphanesi yazmak, 2026'da bazı niş projeler için tercih edilen bir yol haline gelmiştir. ### 3. JavaScript ile Gelişmiş Etkileşim (Callback ve Promise Yönetimi) Go'nun `syscall/js` paketi, JavaScript Promise'leri ve callback'leri ile derinlemesine etkileşim kurmanızı sağlar. Karmaşık asenkron akışları yönetmek için Go'nun goroutine'lerini ve kanallarını kullanmak, JavaScript'teki callback hell veya Promise zincirlerinin karmaşıklığını azaltabilir. ```go // main.go (devamı) func createGoPromise(this js.Value, args []js.Value) interface{} { resolve := args[0] reject := args[1] go func() { // Asenkron bir işlem yapın time.Sleep(2 * time.Second) if time.Now().Second()%2 == 0 { resolve.Invoke("Go Promise başarıyla çözüldü!") } else { reject.Invoke("Go Promise reddedildi!") } }() return nil } func registerGoPromise() { js.Global().Set("createGoPromise", js.FuncOf(createGoPromise)) js.Global().Set("myGoPromise", js.Global().Get("Promise").New(js.FuncOf(createGoPromise))) } func main() { // ... diğer kodlar ... registerGoPromise() <-(chan struct{})(nil) } ``` ```html ``` ## Best Practices & Anti-Patterns Go ile frontend geliştirirken performanslı, sürdürülebilir ve güvenli uygulamalar oluşturmak için dikkat etmeniz gereken en iyi uygulamalar ve kaçınılması gereken anti-pattern'ler. * **✅ Küçük ve Modüler Wasm Modülleri Oluşturun:** Her Wasm modülü belirli bir işlevi yerine getirmeli ve mümkün olduğunca küçük olmalıdır. TinyGo gibi araçlar kullanarak çıktı boyutunu optimize edin. Büyük, monolitik Wasm dosyaları yükleme süresini artırır. * **❌ Gereksiz JavaScript Interop'tan Kaçının:** Go ile JavaScript arasındaki her çağrı bir maliyete sahiptir. Performans kritik yollarda JavaScript'e geçişleri minimize edin. Yoğun döngülerde veya sık çağrılan fonksiyonlarda Go içinde kalın. * **✅ Hata Yönetimini Ciddiye Alın:** Go'nun `error` arayüzünü kullanarak Wasm modülünüzdeki hataları düzgün bir şekilde işleyin. JavaScript tarafına hata mesajlarını ve türlerini açıkça iletin, böylece frontend'de uygun geri bildirim sağlayabilirsiniz. * **❌ Global JavaScript Değişkenlerine Aşırı Bağımlılık:** `js.Global().Get()` veya `Set()` gibi çağrıları dikkatli kullanın. Bu, kodun okunabilirliğini ve test edilebilirliğini azaltabilir. Gerekirse, JavaScript tarafında Go modülünüz için temiz bir API yüzeyi oluşturun. * **✅ Go'nun Eşzamanlılık Modelini Kullanın:** CPU yoğun görevler için goroutine'leri kullanın, ancak unutmayın ki ana Go Wasm iş parçacığı hala tek iş parçacıklıdır. Gerçek paralelizm için Web Workers ile entegrasyonu düşünün. * **❌ Bellek Sızıntılarına Dikkat Edin:** `syscall/js.FuncOf` ile oluşturulan fonksiyon referansları, Go çöp toplayıcısı tarafından otomatik olarak temizlenmez. Artık ihtiyacınız kalmadığında `Func.Release()` çağırarak bellek sızıntılarını önleyin. Bu, production ortamında karşılaştığım ve çözümü zaman alan önemli bir problemdi. * **✅ Güvenlik Odaklı Geliştirme:** Wasm modüllerinin tarayıcıda sandbox ortamında çalıştığını unutmayın, ancak yine de input doğrulama ve yetkilendirme gibi güvenlik best practice'lerini uygulayın. JavaScript ile etkileşimde XSS (Cross-Site Scripting) veya enjeksiyon saldırılarına karşı dikkatli olun. * **❌ Hardcoded Değerler ve Ortam Bağımlılıkları:** Yapılandırma ayarlarını veya API URL'lerini doğrudan koda gömmeyin. Derleme zamanı değişkenleri veya JavaScript'ten enjekte edilen yapılandırmalar kullanın. * **✅ Otomatik Testleri Entegre Edin:** Go'nun yerleşik test araçlarını kullanarak Wasm modüllerinizin mantığını test edin. JavaScript tarafındaki entegrasyon testleri için Cypress veya Playwright gibi araçları kullanın. * **❌ Eski Go Sürümlerini Kullanmaktan Kaçının:** Go'nun 2026'daki güncel sürümü, WebAssembly desteği ve performans iyileştirmeleri açısından önemli yenilikler sunar. Her zaman en son kararlı sürümü kullanmaya özen gösterin. ## Yaygın Hatalar ve Çözümleri Go ile WebAssembly geliştirirken sıkça karşılaşılan sorunlar ve bunların pratik çözümleri. ### 1. `wasm_exec.js` Yüklenmedi Hatası **Problem:** Tarayıcı konsolunda `Uncaught ReferenceError: Go is not defined` veya `WebAssembly.instantiateStreaming is not a function` gibi hatalar görmek. **Sebep:** `wasm_exec.js` dosyası HTML'ye doğru şekilde dahil edilmemiş veya Go modülünüzden önce yüklenmeye çalışılıyor. **Çözüm:** `wasm_exec.js` dosyasının `index.html`'de `` ile `go = new Go()` satırından **önce** ve doğru yolda olduğundan emin olun. Ayrıca, `wasm_exec.js` dosyasını `$(go env GOROOT)/misc/wasm/` konumundan projenizin kök dizinine kopyaladığınızı doğrulayın. ### 2. `syscall/js` Fonksiyon Referanslarının Sızması **Problem:** Uzun süre çalışan Go Wasm uygulamalarında bellek kullanımının sürekli artması. **Sebep:** `js.FuncOf` ile oluşturulan JavaScript fonksiyon referansları, Go tarafında uygun şekilde serbest bırakılmadığı için JavaScript tarafında bellek sızıntılarına neden olabilir. **Çözüm:** `js.FuncOf` ile oluşturulan her fonksiyon için, artık ihtiyacınız kalmadığında `Func.Release()` metodunu çağırın. Özellikle olay dinleyicileri veya callback'ler için bu kritik öneme sahiptir. Örneğin: ```go func registerButton(id string, handler func(this js.Value, args []js.Value) interface{}) { btn := js.Global().Get("document").Call("getElementById", id) jsFunc := js.FuncOf(handler) btn.Call("addEventListener", "click", jsFunc) // Önemli: Eğer bu event listener kaldırılmayacaksa, jsFunc'u global bir değişkende tutun ve // uygulamanın sonlanmasında ya da event listener kaldırıldığında Release() çağırın. // Örneğin: myFuncs = append(myFuncs, jsFunc) } ``` ### 3. `GOOS=js GOARCH=wasm` Olmadan Derleme Hatası **Problem:** Go kodunu WebAssembly'ye derlemeye çalışırken `GOOS` ve `GOARCH` ortam değişkenlerini ayarlamayı unutmak ve standart Go derleme hataları almak. **Sebep:** Go, farklı platformlar için çapraz derleme (cross-compilation) yeteneğine sahiptir. WebAssembly için özel `GOOS` (işletim sistemi) ve `GOARCH` (mimari) değerleri belirtilmelidir. **Çözüm:** Derleme komutunu her zaman `GOOS=js GOARCH=wasm go build -o main.wasm .` şeklinde kullanın. Bu, Go derleyicisine kodu WebAssembly hedefine göre optimize etmesini söyler. ### 4. JavaScript ve Go Tür Uyuşmazlıkları **Problem:** JavaScript'ten Go'ya veya Go'dan JavaScript'e veri aktarırken tür dönüşüm hataları veya beklenmedik davranışlar. **Sebep:** `syscall/js` paketi, temel JavaScript türlerini (string, number, boolean, object) Go türlerine (string, float64, bool, js.Value) dönüştürür. Ancak karmaşık yapılar veya özel türler için manuel dönüşüm gerekebilir. **Çözüm:** `js.Value`'dan Go türlerine dönüşüm yaparken `js.Value.String()`, `js.Value.Int()`, `js.Value.Bool()` gibi metodları kullanın. Karmaşık JSON objeleri için `json.Marshal` ve `json.Unmarshal` kullanarak `js.Value`'yu Go struct'larına dönüştürün. Her iki tarafta da beklenen türleri ve potansiyel null değerleri kontrol edin. ## Performans Optimizasyonu Go WebAssembly uygulamalarından en iyi performansı almak için uygulayabileceğiniz kritik optimizasyon teknikleri ve araçlar. ### 1. Wasm Modülü Boyutunu Küçültme **Ölçülebilir Metrik:** İlk yükleme süresi, ağ bant genişliği. **Strateji:** Daha küçük Wasm modülleri, daha hızlı yükleme ve daha iyi kullanıcı deneyimi anlamına gelir. * **TinyGo Kullanımı:** Özellikle IoT ve WebAssembly gibi kısıtlı kaynaklı ortamlar için tasarlanmış TinyGo, standart Go derleyicisine göre çok daha küçük Wasm çıktıları üretir. Projenizin gereksinimleri uygunsa TinyGo'yu değerlendirin. * **Ölü Kod Eliminasyonu (DCE):** Go derleyicisi ve `wasm-opt` gibi araçlar, kullanılmayan kodu Wasm modülünüzden kaldırarak boyutu küçültmeye yardımcı olur. Derleme sonrası `wasm-opt` aracını kullanmayı düşünün: ```bash GOOS=js GOARCH=wasm go build -o main.wasm . wasm-opt -Oz -o main.min.wasm main.wasm ``` * **Modüler İçe Aktarmalar:** Sadece ihtiyacınız olan Go paketlerini içe aktarın. Tüm standart kütüphaneyi dahil etmek yerine, sadece kullanılan fonksiyonları içeren paketleri tercih edin. ### 2. JavaScript Interop Maliyetini Azaltma **Ölçülebilir Metrik:** Fonksiyon çağrısı gecikmesi (ms). **Strateji:** Go ve JavaScript arasındaki köprü geçişleri (bridge calls) performans maliyetine sahiptir. Bu geçişleri minimize edin. * **Toplu İşlemler:** Sıkça küçük verilerle JavaScript'i çağırmak yerine, verileri Go tarafında toplayın ve tek bir büyük çağrıyla JavaScript'e iletin. Örneğin, DOM'u tek tek güncellemek yerine, bir dizi değişikliği JavaScript'e gönderin ve JavaScript tarafında toplu olarak uygulayın. * **Doğrudan Bellek Erişimi:** Büyük veri setleri için, `WebAssembly.Memory` kullanarak JavaScript ve Go arasında doğrudan bellek paylaşımını değerlendirin. Bu, verilerin kopyalanmasını önleyerek performansı artırır. Ancak bu, daha karmaşık bir yaklaşımdır ve dikkatli bellek yönetimi gerektirir. ### 3. Go Rutin Optimizasyonu **Ölçülebilir Metrik:** CPU kullanımı, UI duyarlılığı. **Strateji:** Go'nun eşzamanlılık modelini verimli kullanın, ancak tarayıcı ortamının kısıtlamalarını göz önünde bulundurun. * **Web Workers ile Paralelizm:** Daha önce bahsedildiği gibi, CPU yoğun görevleri ana iş parçacığından Web Workers'a taşıyarak UI'ın donmasını önleyin. Go goroutine'leri Web Worker içinde hala eşzamanlı çalışabilir, ancak gerçek paralelizm Web Worker'lar aracılığıyla sağlanır. * **Kanal Kullanımı:** Goroutine'ler arasında güvenli ve etkili iletişim için kanalları kullanın. Bu, veri yarışlarını önler ve kodun okunabilirliğini artırır. ### 4. Profiling ve Monitoring Araçları **Strateji:** Performans darboğazlarını tespit etmek için doğru araçları kullanın. * **Go `pprof`:** Go kodunuzdaki CPU ve bellek kullanımını analiz etmek için `go tool pprof`'u kullanın. Her ne kadar doğrudan tarayıcıda çalışmasa da, Node.js ortamında Go Wasm'ı test ederken veya backend ile entegrasyonda faydalıdır. * **Tarayıcı Geliştirici Araçları:** Chrome DevTools gibi tarayıcı araçlarını kullanarak WebAssembly modülünüzün çalışma zamanı performansını, bellek tüketimini ve ağ yükünü izleyin. CPU profiler'ı ve bellek analiz araçları, Wasm modülünüzün nasıl davrandığını anlamanıza yardımcı olur. * **`wasm-pack` ve `wasm-bindgen` (Rust ekosisteminden ilhamla):** 2026 itibarıyla Go Wasm ekosisteminde, Rust'taki `wasm-pack` gibi Go ve JavaScript arasında daha soyut ve optimize edilmiş bir binding katmanı sağlayan araçlar gelişmektedir. Bu araçlar, manuel `syscall/js` kullanımının getirdiği karmaşıklığı ve performans maliyetini azaltabilir. ## Gerçek Dünya Proje Örneği: Go Wasm ile Basit Bir Not Uygulaması Bu örnek, Go WebAssembly kullanarak tarayıcıda çalışan basit bir not alma uygulamasının nasıl oluşturulacağını göstermektedir. Uygulama, notları ekleme, listeleme ve silme işlevlerini içerecektir. **Proje Yapısı:** ``` go-wasm-notes/ ├── main.go ├── index.html ├── wasm_exec.js └── styles.css ``` ### `styles.css` ```css /* styles.css */ body { font-family: sans-serif; max-width: 600px; margin: 20px auto; padding: 20px; border: 1px solid #eee; box-shadow: 0 0 10px rgba(0,0,0,0.1); } input[type="text"], button { padding: 10px; margin-right: 5px; border: 1px solid #ddd; border-radius: 4px; } button { background-color: #007bff; color: white; cursor: pointer; } button:hover { background-color: #0056b3; } ul { list-style: none; padding: 0; } li { background-color: #f9f9f9; margin-bottom: 8px; padding: 10px; border-radius: 4px; display: flex; justify-content: space-between; align-items: center; } li button { background-color: #dc3545; padding: 5px 10px; } ``` ### `main.go` ```go // main.go package main import ( "fmt" "strconv" "syscall/js" ) var ( // Global state for our notes application notes []string nextNoteID int ) func main() { fmt.Println("Go Wasm Not Uygulaması Başlatılıyor...") // Register Go functions to be called from JavaScript js.Global().Set("addNo