- Go eleştirilerine karşı tekrar eden “büyük şirketler de kullanıyor”, “iyi yanları da var”, “doğruluk maliyetlidir” gibi itirazlar, dil tasarımı kusurlarının uzun vadeli maliyet olarak birikmesi sorununu bulanıklaştırabilir
- Go; asenkron runtime, GC, paket yönetimi, refactoring ve çapraz derleme araçlarında güçlüdür; ancak özel toolchain’i, build sistemini, çağrı konvansiyonunu, tek GC’yi ve ekosistemi de birlikte kabul etmeyi gerektirir
- sum type eksikliği, değiştirilebilirliği kontrol etme yetersizliği, zero value ve
nilslice/map/channel’ların farklı davranışları nedeniyle derleyici birçok invariant’ı koruyamaz - cgo olmadan diğer diller ve araçlarla entegrasyon zordur; cgo kullanınca da GC ve pointer kuralları, runtime’ı dahil etme ve büyük statik kütüphane yükü ortaya çıkar; bu yüzden ağ sınırı en gerçekçi entegrasyon noktası hâline gelir
- “Prototipi Go ile yapar, sonra yeniden yazarız” beklentisi pratikte yeniden yazımdan kaçınma, mevcut Go koduyla bağlanma, linter/dokümantasyon/manuel doğrulama yükleri nedeniyle operasyon maliyetini artırabilir
Go eleştirilerinde tekrar eden savunma mantığı
- 2020’deki I want off Mr Golang’s Wild Ride yazısından sonra Go eleştirileri etrafındaki tepkiler sürekli tekrarlandı
- Windows örneğinin Go’nun iyi olduğu alan olmadığı tepkisi
- Go’nun iyi yanlarından bahsetmediği tepkisi
- Go’nun seçtiği ödünleri anlamadığı tepkisi
- Büyük şirketler Go kullandığı için çok kötü olamayacağı tepkisi
- Sorunu “doğru” modellemenin maliyeti yüksek olduğundan doğruluk tartışmasının anlamsız olduğu tepkisi
- Rust’ın da eksileri olduğu için Go eleştirisinin geçersiz olduğu tepkisi
- Asıl mesele Go’nun avantajları olup olmadığı değil, Go kullanmaya devam etmek için tekrarlanan savunma mantığının gerçek maliyeti gizleyip gizlemediğidir
Önce eleştirmenin yetkinliğine saldırma yöntemi
- Duymak istemediğiniz bir geri bildirim geldiğinde, bunu söyleyen kişinin yetersiz ya da gizli bir motivasyona sahip olduğunu varsayarsanız içeriği incelemenize gerek kalmaz
- Bir sorunu fark etmek için mutlaka yüksek uzmanlık gerekmez; kıdemli geliştiriciler alıştıkları rahatsızlıkları aksine görmezden gelebilir
- Junior geliştiriciler henüz tuhaflıklara alışmadıkları için rahatsızlığı daha hızlı hissedip soru sorabilir
- Geri bildirimin değeri, kimin söylediğinden çok gerçekten bir sorun olup olmadığına göre değerlendirilmelidir
“Başka şirketler de kullanıyor” gerekçesinin sınırları
- Teknoloji seçiminde başka şirketlerin ne kullandığına bakmak keşif için yararlıdır; ama benimseme gerekçesi olarak yeterli değildir
- Şirket teknoloji blogları genellikle benimseme maliyetini tam olarak ortaya koymakta zorlanır
- Çoğu zaman karar zaten verildikten sonra yazılırlar
- Şirket imajını iyi göstermek ve işe alıma yardımcı olmak gibi amaçları vardır
- Güçlü teknik eleştiriler çoğunlukla şirketlerden değil bireylerden gelir
- Tailscale’in Go kullanımı, maliyeti bilen ve kaldırabilecek bir Go uzmanları ekibinin örneğine daha yakındır
- netaddr.IP: a new IP address type for Go IPv4 veya IPv6 adresini temsil etme sürecinde Go’nun kısıtlarını ortaya koyar
- Hey linker, can you spare a meg? Go linker’ı hakkında derin bilgi gerektiren bir sorunu ele alır
netaddr.IPte görülen acının nedeni Go’nun çeşitli kısıtlarıyla iç içedir- Go’da sum type olmadığı için “IPv4 veya IPv6” tipini ifade etmek hantaldır
- slice, 64-bit makinelerde 24 bayt maliyeti olan genel amaçlı bir veri yapısı olarak kullanılır
- Operatör overload’u olmadığı için
a == bilea.equals(b)gibi ayrımlar ortaya çıkar - Immutable veri desteklenmediği için kopya geçirmek ve içerideki değişikliklere dikkat etmek gerekir
- Opak bir
newtypeoluşturmak zor olduğundan ayrı paket ve interface üzerinden dolanma gerekir
- Tailscale gibi ekipler Go’nun iç işleyişini ve sınır durumlarını derinlemesine ele alabilir; ancak her kurum Google veya Tailscale gibi Go uzmanlarına ve mühendislik maliyetini karşılayacak imkâna sahip değildir
Go’nun gerçekten iyi yaptığı şeyler
- Go oldukça iyi bir asenkron runtime, güçlü görüşlere sahip varsayılanlar, iki ayar düğmesi olan modern bir GC ve iyi bir araç zinciri sunar
- Asenkron runtime dilin merkezinde olduğu için Rust geliştiricilerinin imrenebileceği araçlar da vardır
- Çalışan tüm goroutine’lerin backtrace’ini kolayca dump edebilirsiniz
- Deadlock tespiti mümkündür
- Kendi profiler’ı vardır
- Function coloring’i daha az düşünmenizi sağlar
- Paket yönetimi, refactoring ve çapraz derleme araçları; C ekosistemindeki
pkg-config, autotools ve CMake’e kıyasla başta bir iyileşme gibi gelir - Ancak Go’nun kullanışlı runtime’ını tek başına seçip kullanmış olmazsınız
- Özel toolchain
- Build sistemi
- Çağrı konvansiyonu
- Tek GC
- Dahil edilmiş standart bileşenler ve ekosistem
- Tesadüfen şekillenmiş dil tasarımı da birlikte benimsenir
Tip sistemi ve dil tasarımındaki boşluklar
- Go; TCP, HTTP, TLS, HTTP/2, DNS ve web servisleri uygulamaya yönelik runtime’ı merkeze alır ve Java/C/C++/Python öğrenmiş Google geliştiricilerine tanıdık gelecek bir biçim alır
- C gibi hata işlemeyi kendi başına fazla ele almaz; çok sayıda değiştirilebilir durumu geliştiricinin
ifveelseile doğrudan yönetmesi gerekir - Java gibi değer ve referans ayrımını bulanıklaştırır; yalnızca çağrı noktasına bakarak değerin değişip değişmeyeceğini anlamak zordur
- Method receiver’ın
Amı yoksa*Amı olduğuna bağlı olarakmainiçindeki yerel değişkenadeğişebilir ya da değişmeyebilir
- Method receiver’ın
- Değiştirilebilirlik ve değişmezliği tiplerle net biçimde sınırlamak zor olduğundan, referans geçirilirken iç değerlerin değişmesi veya uzun süre tutulup serbest bırakılmaması riski vardır
- Go aşağıdaki hata gruplarını yeterince engelleyemez
- Mutex’in yanlışlıkla kopyalanıp etkisizleştirilmesi
- Struct alanlarının initialize edilmemesi ve zero value alması
- Yanlış
nil, zero veya empty string’in sistemin derinlerine yayılması
zero value ve “dikkat edersen yeter” yaklaşımının sınırları
- Bir struct’a yeni alan ekleyip fiilen fonksiyon girdisinin biçimini değiştirseniz bile, composite literal’da yeni alan atlanırsa derleyici bunu engellemez
- Örnekte
Paramsab int32eklenmiştir; ancak çağıran taraf yalnızcaa: 47geçirirseb=0ile çalışır - Buna karşılık fonksiyon argümanını doğrudan eklerseniz argüman sayısı yetersiz olduğundan derleme hatası oluşur
- Örnekte
- Go’nun ilkelerinden biri zero value’nun kullanışlı olmasıdır; ancak gerçek anlamı tipe göre değişir
nilslice üzerindelençağrılırsa sonuç 0’dır ve boş slice gibi davranırnilmap’e değer koyarsanızpanic: assignment to entry in nil mapoluşur
- Channel’lar için de ayrı kurallar vardır
nilchannel’a send yaparsanız sonsuza kadar block olurnilchannel’dan receive yaparsanız sonsuza kadar block olur- Kapalı channel’a send yaparsanız panic oluşur
- Kapalı channel’dan receive yaparsanız zero value hemen döner
- Go’da sum type olmadığından “yalnızca bilinen seçeneklerden birine izin veren” girdiyi tip olarak ifade etmek zordur; C’deki gibi “sadece dikkatli ol” yaklaşımına yakındır
- Tüm sorunları engelleyemiyoruz diye bazı sorunları da engellemeye gerek olmadığı tutumu yanlış bir ikilemdir; tip sisteminin yardımcı olabileceği sorunlar bile manuel dikkate bırakılır
Rust karşılaştırması “kusursuz alternatif” tartışması değildir
- Buradaki duruş Rust’ın kusursuz olduğu değildir; Go ve Rust farklı biçimlerde başarılı örnekler olarak görülebilir
- Go’nun başarısı büyük ölçüde dahil edilmiş bileşenlere ve güçlü görüşlere sahip varsayılanlara dayanır
- Rust’ın başarısı büyük ölçüde kademeli benimsemeye ve diğer dillerle entegrasyon kolaylığına dayanır
- Gerçek Rust benimseme örnekleri, komple değiştirmeden çok kademeli port etmeye yakındır
- Firefox, büyük bir C++ kod tabanı içinde birkaç temel Rust bileşeni içerir
- Android, Bluetooth stack’ini Rust ile yeniden uyguladı
- Rust kriptografi kodu Python’a girdi; Rust HTTP kodu curl’ün çeşitli backend’lerinden biri oldu
- Linux kernel Rust patch’i tekrar tekrar iyileştiriliyor
- Rust kullanıcıları da build süreleri, dil özelliği eksiklikleri ve diğer dezavantajlar hakkında aktif biçimde konuşur
- Tartışma Go ile Rust’tan birini koşulsuz seçmek değil; değiştirilebilirlik, yaşam süresi ve soyutlamaları tiplerle ifade edebilen araçların hangi sorunları azalttığıdır
- Rust’ta da her durumu katı biçimde modellemeyebilirsiniz
- Örneğin düşük seviyeli
lsbenzeri bir araç değilse yalnızca UTF-8 path’lerle çalışmak için camino kullanmayı seçebilirsiniz - Hata işlemede yalnızca birkaç önemli variant’ı listeleyip geri kalanını
Other,Internal,Unknownolarak bırakabilirsiniz Option<T>için unwrap() çağırmak, değerin var olduğunu açıkça iddia etme biçimidir
- Örneğin düşük seviyeli
Go diğer ekosistemlerden kopuk bir adaya daha yakındır
- cgo kullanmazsanız Go; alışılmış assembly, linker, debugger, bellek denetleyicileri ve çağrı konvansiyonlarından uzaktır
- Go, C/C++’tan çok closed-world bir dile yakındır; Node.js, Python ve Ruby’ye kıyasla FFI’ye daha düşmancadır
- Bu farkın avantajları da vardır
- TLS ve HTTP stack’inin içini iş mantığıyla aynı şekilde profiler’da görebilirsiniz
- Dinamik dillerde stack trace’in OpenSSL’de durmasıyla tezat oluşturur
- Runtime non-blocking I/O ve scheduling’i yönetebilir
- Ancak mevcut birçok aracı ve kurumsal bilgiyi olduğu gibi kullanmak zordur; Go ile başka dilleri entegre etmek de zahmetlidir
- Go entegrasyon yöntemlerinin her birinin maliyeti vardır
- Go’dan C çağırırsanız FFI sınırı maliyetinin yanında GC’yi bozmamak için manuel descriptor takibi gerekir
- Başka bir dilden Go çağırırsanız GC dahil tüm Go runtime’ını birlikte koymanız gerekir; büyük statik kütüphane ve operasyon yükü doğar
- Go ile temas eden en iyi sınır ağ sınırına yakındır
- REST-ish HTTP/1, JSON-RPC ve gRPC gibi TCP üzerinden RPC yaklaşımları, gecikme maliyetini kaldırabiliyorsanız görece daha az acı verir
- Yine de iki tarafta da invariant’ları korumak gerekir; Go tarafında doğrulama paketleri düzenli kullanılmazsa derleyici bunu garanti etmez
Prototip için Go beklentisinin tuzağı
- Go’nun öğrenmesi ve işe alımı kolay olduğu için önce prototip yapıp, işler zorlaşınca daha sonra yeniden yazma veya uzman getirme düşüncesi vardır
- Ancak “atılacak kod” pratikte neredeyse yoktur
- Yeniden yazmak zaman alır
- Sorunsuz geçiş koordinasyonu zordur
- Ayrıntılar kaybolabilir
- Yeni özellik geliştirme durur
- İnsanları yeni teknolojiye göre yeniden eğitmek gerekir
- Go bileşenleri arttıkça mevcut Go koduyla etkileşim kurmak için Go seçmeye devam etme nedenleri de artar
- Linter’lar bir ölçüde yardımcı olur; ancak sorunu baştan ciddiye alan bir dilin derleyicisi kadarını yapamaz ve geliştirme hızını da düşürür
- Dilde bulunmayan karmaşıklık kod tabanına taşınır
- Tiplerle ifade edilmeyen invariant’lar kodla doğrudan yazılmak zorundadır
- Yalnızca fonksiyon imzasından verinin değiştirilip değiştirilmeyeceğini, saklanıp saklanmayacağını, zero value’ya izin verilip verilmediğini, goroutine başlatılıp başlatılmadığını,
nilchannel olasılığını veyainterface{}e gerçekte hangi tiplerin geçirilebileceğini anlamak zordur - Dokümantasyona bağımlı olunur; dokümantasyonun hem güncelleme hem de güncellenmeme maliyeti yüksektir
Sonuçta özetlenen “yalanlar”
- Go kullanmaya devam etmek için kendimize söylediklerimiz şöyle özetlenebilir
- Başkaları kullandığına göre bizim için de iyi olacaktır
- Endişelerini dile getiren kişi elitist ya da kaba biridir
- Cazip asenkron runtime ve GC diğer tüm eksileri telafi eder
- Her bir dil tasarımı kusuru tek başına da, birleştiğinde de sorun değildir
- “Dikkatli olmak”, linter’lar ve daha fazla reviewer ile üstesinden gelinebilir
- Yazması kolay olduğu için production yazılım geliştirmek de kolaydır
- Dil basit olduğu için geri kalan her şey de basittir
- Azıcık kullanırız ya da sadece başta kullanırız; kolayca çıkabiliriz
- Daha sonra istediğimiz zaman yeniden yazabiliriz
- Seçilen araç karmaşıklığı ortadan kaldıramıyorsa, bu karmaşıklık başka geliştiricilere, operatörlere ve müşterilere taşınır
nildeğerlerin girmemesi gereken yerlere girip production’da gece uykunuzdan uyandırdığı durumlar, Billion Dollar Mistake’in tekrarına dönüşür
2 yorum
Go diliyle çok kısa ama yoğun bir süre geçirmiş bir amatörün yazı bırakması ne kadar uygun emin değilim ama... Go dilinin artıları ve eksileri gerçekten çok net; bu yüzden onu seçenlerin de kaçınanların da belli nedenleri var gibi görünüyor. Bana kalırsa bunu Rust ile değil, Kotlin(Java) ile karşılaştırmak daha doğru.
Go'nun goroutine'leri gerçekten harika, ama sihir değil. Özellikle backend tarafında sadece tek bir MySQL kullanan küçük projelerde bu eşzamanlılık meselesini yönetmek gerçekten zor. JS/TS runtime'larında çok da dert etmediğiniz MySQL kaynak tükenmesi ya da pool yönetimi, düşündüğünüzden daha zor olabiliyor. Sonuçta bu durumda darboğaz DB olduğu için Go dilinin eşzamanlılık avantajı kısmen soluyor. (JS/TS runtime'larının asenkron I/O'su ya da event loop'u hatta daha uygun olabilir.) Bunu
heygibi bir araçla-c 100verip denediğinizde hemen anlayabilirsiniz.Ayrıca iyi bir GC var diye, nesneleri gelişigüzel sadece pointer geçirerek kullanıp temizliği tamamen akışına bırakamazsınız. Her şeyde olduğu gibi burada da trade-off var; Go dilinde de mümkünse küçük nesneleri doğrudan değer kopyasıyla aktarmak ve fonksiyon biter bitmez işlerinin kapanmasını sağlamak daha iyi. Belki eski düşünce tarzına saplanmış olabilirim ama, C/C++ dillerindeki verimlilik bakışıyla pointer'lara kolayca yaklaşmamak gerekiyormuş.
Fonksiyondan
errordönerken neredeyse her seferinde geri döndürmek ve onu her seferindeif err != nil {}ile kontrol etmek gerçekten yorucu, ama bu bir avantaj. Çünkü maliyetitry catch'ten daha düşük. Ayrıcafinally {}benzeri bir rol üstlenendeferanahtar sözcüğü de harika. Kaynağın ne zaman serbest bırakılacağını düşünmek zorunda kalmamak güzel. Sadece standart kütüphane ile bile gayet iyi bir backend sunucu yapısının hemen kurulabilmesi de güzel (1.23 ve üzeri). Hepsinden önemlisi, hedef OS'e göre build edildiğinde başka bir runtime'a ya da ön kurulumlara ihtiyaç duymaması bence en büyük artısı.Go dilini uzun süre kullanmadım ama fazla kişisel bir görüşü uzatıyormuşum gibi hissettiğim için burada keseyim. haha Ben Go dilini de seviyorum, diğer dilleri de!
Hacker News yorumları
Bu yazı Go’nun eksilerini büyük ölçüde iyi yakalıyor, ama açık hata işlemenin bunlardan biri olduğunu düşünmüyorum.
İstisna işlemeyi, çok kolay bozulabilen bir “sihir” katmanı eklediği için hiç sevmedim; teknik olarak kusursuz bir argüman olmasa da onlarca yıllık deneyimim, hataların tam ortaya çıktığı noktada ele alınmasını tercih ettiriyor.
Rust’ın bunu daha zarif yaptığını söyleyebiliriz ve kişisel projelerde Rust’ı daha çok seviyorum; ama farklı yetkinlik seviyelerinde geliştiricilerin girip çıktığı büyük projelerde Go’nun felsefesini modern hata işleme yaklaşımları içinde epey makul buluyorum.
Benim bölgemde Go, sadeliği sayesinde diğer “yeni” dillere kıyasla çok daha fazla benimseniyor. En iyi dil değil, ama kendinize zarar vermenizi engelleyen yerleşik çok sayıda sağduyu içerdiği için genel amaçlı bir dil olarak çoğu zaman en iyi seçenek oluyor.
Stack trace yok ve hataları sarmalamak gerekiyor; bu yüzden yalnızca benzersiz hata mesajları değil, her çağrı noktası için benzersiz sarmalama mesajları da üretmeniz gerekiyor ki mesajlarda
grepyapıp stack trace benzeri bir şeyi tahmin edebilesiniz.“Dönüş tuple’ı”, yalnızca hatalar yüzünden var olan tuhaf bir düzenek; dilin başka yerlerinde tuple bile kullanamıyorsunuz. Garip değişken başlatma kuralları yüzünden bir gün mutlaka yanlış
errdeğişkenini kullanıyorsunuz.Go’da enum olmalıydı ya da yalnızca hatalara özel tuhaf bir “dönüş tuple’ı” yerine Rust’taki
?gibi daha iyi bir söz dizimsel şeker eklenmeliydi. Mevcut yöntem sıkıcı ve hataya açık.Go’nun inatçı bir duruşu var, ama bu çok sık, dili eleştiriden korumaya çalışan bir inat gibi görünüyor. Ne yazık ki bir programlama dilinin popülerlik kazanmasında pazarlama, yani yalanlar da önemli; bu yüzden işe yarıyor.
İstisnalar, herhangi bir kütüphanenin koduma fırlatabileceği berbat bir
gotodur ve neredeyse hiç düzgün işlenmez. Bir istisna “işlendikten” sonra bile uygulama genellikle bilinmeyen bir duruma düşer ve hakkında akıl yürütülemez hale gelir.Go hatalarını junior mühendisler bile çoğunlukla kolayca debug edebilirken, Java istisnalarının gerçek nedenini deneyimli principal’lar bile anlamakta zorlanır.
Buna karşılık Maybe, Option, Result gibi sum type’lara aşina olup da Go’nun yaklaşımını az da olsa iyi bulan birini henüz görmedim.
Belirli bir metodun mantığını okumaya çalışırken satırların %75’i hata gürültüsü, yalnızca %25’i gerçek davranışı anlamak için gerekliyse bunu okumak zordur.
Bir kod tabanına ilk baktığımda, hata uç durumlarından önce neyi başarmaya çalıştığını bilmek isterim; sonra bunun doğru olduğunun nasıl güvence altına alındığına bakarım.
Bu açıdan Go’nun hata işlemesi büyük ölçüde başarısız. Açık hata işlemenin kötü olduğu değil; sorun, başarı yolu ile hata işlemeyi satır satır birbirine karıştırma ısrarı. Özel bir hata işleme bölümünde de açık biçimde işleyebilirsiniz.
Katıldığım nokta, kodun üretebileceği tüm olasılıkları düşünmeye zorlaması. Yalnız bu, diğer dillerden çok C’ye yakın bir soru.
Kodu soyutlarken hatayı hemen ele almanız gerekmeyebilir ya da çağrı yığınının daha aşağılarında ele almak isteyebilirsiniz.
Dilin belirli bir yöntemi dayatması için okunabilirlikten epey feragat edilmiş oluyor.
Rust ve Go çok farklı; insanlar sanki şu anda mevcut olmayan bir orta nokta istiyor gibi görünüyor
Çöp toplaması olan, nispeten basit, statik bağlı ikili dosyaya derlenen; ama Rust’a benzer bir tip sistemi ve remainder type gibi şeyleri olan bir dilden söz ediyorum
Sözdizimi açısından Gleam ve Kotlin bir ölçüde buna yakın, ama tam olarak değil. Rust’ı seviyorum; ancak bir şeyler inşa etme yeteneği olsa da bilgisayar bilimi mezunu olmayan ve programcı olarak çalışmayan birçok kişi için fazla karmaşık olduğunu düşünüyorum
Dili yalnızca ara sıra kullanıyorsanız vtable’ın ne olduğunu, bir değerin ne zaman ve nasıl serbest bırakıldığını hatırlamazsınız. “Mükemmel dil” yok, ama Go ve Rust’ın ikisi de harika şeyler getirdi; umarım biri ikisinden ilham alıp yaygın kullanılabilecek basit bir dil yapar
Gerçekte Kotlin oldukça karmaşık; akıllıca davranmaya çalışırken zaman harcıyorsunuz. Bir işi yapmanın 1000 yolu var; operatör aşırı yükleme, proxy’ler, property’ler, companion object’ler, exception’lar ve result type’ların hepsi mevcut
Gradle kullandığınızı varsayarsak, derleme sistemi
go builde alışkın biri için işkenceye yakınCoroutine API’si Goroutine’lerden aynı anda hem daha karmaşık hem de daha kısıtlayıcı hissettiriyor. Daha yapısal, ama daha az esnek ve kullanmak için daha fazla çaba gerektiriyor
Erişim denetimi de tuhaf. Bir tipi pakete özel yapmanın yolu yok; ya dosyaya özel ya da tüm modüle açık. Bu yüzden istemeden API yüzeyi büyüyor ya da karmaşıklığı birden fazla dosyaya bölemiyorsunuz
Kotlin/Native ve Kotlin/JVM fiilen farklı şeyler. Kotlin/JVM olgun, ama JVM üzerinde çalıştığı için Rust’ı tercih edeceğiniz kullanım alanlarının bir kısmı ortadan kalkıyor
Kotlin/Native ekosistemi çok zayıf, belgeleri de yetersiz. Issue tracker’da korkutucu hatalar da var
Kotlin/Native, yalnızca kaynak koddan oluşan kütüphane dağıtımını bile yapamadığı için tüm işletim sistemleri ve mimariler için ikili dosya derleyen karmaşık bir CI gerekiyor. Ya da kütüphaneyi hiç dağıtmıyorsunuz; bu da zayıf ekosistemi daha da kötüleştiriyor gibi
Generic’lerin eklenmesi gibi, sadece üç şey eklemek yeterli: hatalar için generic bir container olan Result, daha iyi nil işleme için Optional ve Elvis operatörü gibi küçük bir sözdizimi şekeri
Go’nun başarısını neredeyse tek başına açıklayan büyük avantaj, dev bir şirket tarafından geliştirilmesi ve bizzat kullanılması; bu sayede harika araçlar ve açık kaynak kütüphaneler üretme kapasitesine sahip olmasıydı. Halihazırda kullanılıyor olması ve kütüphanelerinin bulunması, bir dilin başarısındaki en büyük belirleyici gibi görünüyor
Temel sözdizimi çok doğrudan, benimsenmesi zaten muazzam, ekosistemi büyük, çalışma zamanı sürekli iyileşiyor ve WASM’e derlenebiliyor
Buna, tuhaf kısımları —örneğin aşırı yeniden tanımlama esnekliği, global scope’un kötüye kullanımı, sayılarla ilgili gariplikler— çıkarıp tipler, sum type/product type, Result, Maybe, decimal vb. ekliyorsunuz
Ayrıca her şeyin ifade olduğu bir tarz, pattern matching, currying gibi fonksiyonel özellikler ve kapsamlı bir standart kütüphane koyarsanız, birçok insanın istediğine en yakın dil ortaya çıkabilir
Geliştirici araçlarında görmek istediğim bir başka büyük ilerleme de HTML’i elden geçirip doğru düzgün üst seviye kontrolleri yerleşik hale getirmek ve inline CSS ile kolayca stillendirilebilir kılmak. Böylece istemcide gereken JS miktarı azalır
Bu iki şeyin web ile ilgili geliştirmelerde programlama üretkenliğini ciddi biçimde artıracağını düşünüyorum
dotnet publish -p:PublishAot=trueile statik native binary olarak derleyebilirsiniz. F#’taprint*yerineConsole.*metotlarını kullanmak gerekiyor; çünküprint,%Abiçim belirtecinin yapısal çıktısı nedeniyle içinde sınırlandırılmamış reflection barındırıyor, bu da binary boyutunu olumsuz etkiliyor ve derleyici şikâyet ediyorÖzellikle F#, “daha kolay ve iş odaklı bir Rust alternatifi” olarak önerilebilir. Expression-oriented bir dil; discriminated union’lar, eksiksiz HM type inference ve gradual typing iyi uyum sağlıyor. Veri analizi ve domain modeling de çok rahat
Sistem programlama için C# bir seçenek haline geliyor. Harika eşzamanlılık temel öğeleri, hızlı ve bazen neredeyse sıfır maliyetli native interop, Go’dan daha küçük native binary’ler ve taşınabilir SIMD dahil birçok düşük seviye API sunuyor
Go bu tür işlere çoğu zaman pek uymuyor ya da dolambaçsız şekilde hiç yapamıyor. .NET bu alandaki oyun dışı toplulukta popülerlik kazanıyor ve yüksek performanslı çok sayıda kütüphane de ortaya çıkıyor. Ayrıca kardeş yorumda önerilen niş dillerin aksine, devasa mevcut ekosistemden yararlandığı için tüm temel işleri kendiniz yapmak zorunda kalmıyorsunuz
Go: “Ben basit bir dilim!”
Kullanıcı Go’yu bir süre kullanır
Kullanıcı: “Senden nefret ediyorum, sen basit bir dilsin!”
Ben 50’li yaşlarımda ya da üstünde olduğumdan mıdır bilmem, basit dilleri seviyorum
Bu “eleştiri” pek dengeli görünmüyor; teknolojide her şey bir ödünleşimdir ve dengesiz yargıların zayıf olduğunu düşünüyorum
Elbette benim vardığım sonuç farklı: https://www.inkmi.com/blog/why-we-chose-go-over-rust-for-our...
Yazıda dilin can sıkıcı tutarsızlıklarına işaret eden çok sayıda örnek var ve bunlar basitliğin zıddı
Rob Pike’ın Go sunumunu seviyorum; bazı kısımları benim için ufuk açıcıydı. Ama pratikte gördüğüm Go’nun, Go hayranlarının soyut olarak anlattığı Go’ya çok daha yakın olmasını isterdim
Göründüğünün aksine, Go kullanmaya başlayınca kısa sürede basit olmadığı ortaya çıkıyor. Çok sayıda gizli karmaşıklık ve tuzak var. Örn: https://archive.ph/WcyF4
Yine de kullanışlı bir dil ve epey kullanılıyor, ama “basit” değil
Basit bir dilin yüksek tutarlılığa sahip olması gerektiğini düşünüyorum. Kurallar az olmalı ama her yerde genel ve tutarlı olmalı. Oysa Go’da her yerde tuhaflıklar, tutarsızlıklar ve dolambaçlı çözümler var
Buna iyi bir örnek tipin atlanması. Dizi, slice ve map bildirimlerinde mümkün, ama struct’larda değil. Struct’larda da izin verilse okunabilirlik açısından birçok avantajı olurdu; anonim struct argümanları üzerinden adlandırılmış parametreler de mümkün hale gelir, bu da bugün kullanılan çirkin dolambaçlı çözümlerden çok daha iyi bir tasarım sağlayabilirdi
Elbette Go’nun makul alternatiflerinin çoğu da bu açıdan daha kötüdür. Python, Ruby, JS gibi şeyler
Herhangi bir dili bu kadar uzun uzadıya yerden yere vurmaya iten motivasyonun ne olduğunu merak ediyorum. Yazıdaki bazı geçerli noktalar bile yapıcı bir üslupla yazılmadığı için buna suçlama diyeceğim
Eleştirilemeyecek dil mi var?
O projede yaşanan başarısızlığı dile yükleyip kendini daha iyi hissetmek için yazılmış bir yazı mı? Yoksa herkesin aynı şekilde düşünüp çalışmadığını, birine dayanılmaz derecede batan bir şeyin başkasının neredeyse hiç gözüne çarpmayabileceğini anlayamamak mı?
Gerçek ihtiyaçları karşılamayan diller genellikle kendiliğinden kaybolur; bunun için pek yardıma ihtiyaç duymazlar
Go, “daha rafine” dillerden farklı yanları olsa da benim karşılaştığım projelerde harika çalıştı. Umarım yazar Go ile çalışmaya zorlanmıyordur. Topluluğun geri kalanı hizmetler geliştirmeye, Go ekibine geri bildirim vermeye ve dili prodüksiyonu bozmadan yavaş yavaş evrilirken izlemeye devam edecek
Özsel karmaşıklık gözlerini kapatınca ortadan kaybolmaz
Karmaşıklığı umursamamayı seçersen, o karmaşıklığı sadece organizasyondaki başka geliştiricilere, operasyon ekibine, müşterilere, birilerine itmiş olursun. Artık her şeyin sorunsuz işlemesi için senin varsayımlarının etrafından dolaşmak zorunda olanlar onlar
Son zamanlarda o “birileri” çoğu kez ben oluyorum ve artık yoruldum
Go’nun karşılaştığın projelerde harika çalışmış olması doğal. C, C++, PHP, JavaScript de çalışıyor. Dünyamızda pek çok şey “çalışıyor”. Bir şerit daha eklemek de çalışıyor, polis devleti de çalışıyor
Ama başka bir şey çok daha iyi çalışıyor olamaz mı?
Neden yazdığına gelince, muhtemelen asıl yazar kendi görüşünün “dünyada” yeterince temsil edilmediğini hissettiği içindir. Ben de Go hayranı değilim; 2022’de Go’nun popülerliği bana kafa karıştırıcı geliyordu. Çünkü epey belirgin bazı eksileri yok sayılıyor gibi görünüyordu
PHP’nin kötü bir dil olduğuna dair uzun blog yazılarını artık pek kimse yazmıyor; çünkü bu konu zaten fazlasıyla işlendi
Bu blog yazısının senin hoşuna gidecek şekilde yazılmamış olması, başkaları için değer taşımadığı anlamına gelmez
Go’nun yaptığı her şey, ister en temel uygulama olsun ister başka dillerin zaten daha iyi yaptığı bir şey olsun, vazgeçilmez, en iyi ve o sorunu çözmenin tek yolu gibi sunuldu
Go’nun yapmadığı her şey ise gereksiz ve biz aydınlanmamış Go dışı kullanıcıları sözdizimsel şekere bağımlı kılmaya çalışan Big Complexity’nin komplosu gibi muamele gördü. Düzgün null işlemesi, hata işleme, daha az boilerplate, generics ya da her şey için özel durum üretmeden tutarlı çözümler oluşturmak gibi özellikler buna dahildi
Bu başlıkta bile saman adam dövmeye devam ediliyor. Hata işleme konusu açıldığında, Go’nun hata işlemesinin çok daha iyi olabileceği gibi bariz bir gerçeği kabul etmek yerine JavaScript gibi şeyler ortaya atılıyor. Sanki Go’yu eleştiren kişi JavaScript’i hata işlemenin zirvesi sanıyormuş gibi
Başka dillerle çalıştığım her seferinde, Go mükemmel bir dil olmasa bile hep ona geri dönmek istiyorum
Kelimenin tam anlamıyla öylece çalışıyor olmasını seviyorum. Go’yu kur, kodu indir, kodu yaz; hepsi bu
Hangi sürümü, runtime’ı, ayarı, build aracını, paket yöneticisini kullanacağını çözmen gerekmiyor. Sadece kurup Go kullanıyorsun
Aynı deneyimi sunan başka bir dil muhtemelen en fazla Rust’tır
Kendimize söylediğimiz bir yalan olabilir ama Python, TypeScript, Java kullandığım her seferinde sadece kod yazmak isterken ayarları, paket yöneticilerini, build araçlarını ve sürümle ilgili sorunları debug etmek ya da anlamaya çalışmak yüzünden programlama gözümde korkutucu hale geliyor
Go eleştirilerini her okuduğumda aynı şeyi düşünüyorum. Yine de Go kullanmaya devam edeceğim
Teoride kolayca belgelenebilecek çok sorunu olduğunu ve insanların pratikte de bunlara sıkça takıldığını anlıyorum; ama yine de gerçek işlerde hâlâ daha iyi programlama dillerinden biri gibi geliyor
Genelde dezavantaj diye listelenen bazı şeylere katılmıyorum; örneğin her yerde hataları açıkça ele alma biçimini seviyorum. Diğer konularda katılıyorum ama bunlar bana diğer programlama dillerinin kusurlarından çok daha fazla batmıyor
Go’nun başarılı olamadığı alanlara özellikle hassas olan insanların ömür boyu bundan şikâyet edecek olması üzücü geliyor
Ama bir projede hangi dili kullanacağıma karar verirken “en iyi dil hangisi” diye bir sürü rasyonel argüman sıralamıyorum. Bana uyan, iyi yazılımı istikrarlı biçimde yazabileceğimi hissettiren ve çalışması keyifli olan dili seçiyorum
Doğruluğa önem veren biri olarak o dilin Rust’a daha yakın olmasını isterdim ama şu anda öyle değil. Rust’tan nefret ettiğimden de değil; sadece acelem olduğunda elim onun üzerine gitmiyor
Go’nun ne kadar berbat olduğuna dair artık yeterince çok yazı yazıldı. En azından birkaç yıl önce PHP hayranı olmanın nasıl bir his olduğunu artık biliyorum. Abartı, ama bence çok büyük bir abartı değil
Go kullanacaksınız
Ve pişman olacaksınız
Ama o zaman artık çok geç olacak ve ona bağlanmış olacaksınız
Yazar oldukça ikna edici bir argüman kuruyor ve buna karşı çıkmak da çok zor. Açıkça listelenen pek çok durumda ve teknik açıdan yetkin olmayan bir şirketin uygun olmayan bir teknolojiyi kullandığı birçok profesyonel senaryoda Go kötü bir seçimdir; bunu production’a koyduğunuza pişman olursunuz
Şirketler sıkıcı araçlara bağlı kalmalı. Kişisel projeyse tabii ki istediğinizi yapabilirsiniz
Bunun dışında sadeliğini güçlü yön olarak görüyorum. Kullanımı güzel, öğrenmesi kolay ve genel olarak performansı da epey iyi. Her durum için seçmem ama iyi bir araç olduğu çok senaryo var
Benzer şekilde Java ve Python’ı da bir ölçüde seviyorum; ikisinde de yeterince iyiyim. Bu diller, amaçladıkları şeyler için iyi araçlar
İnsanların programlama dillerine neden bu kadar tutkuyla bağlandığını bilmiyorum. Diller araçtır. Bazı araçları daha çok sevebilirsiniz ama sevmediğiniz bir aracın geçersiz olduğu anlamına gelmez
if err != niliblislerinin yüzüme vurduğu kâbuslar görüyorumBu sorunu düzeltmek için çok sayıda iyi öneri vardı; ama aşırı muhafazakâr ve sesi çok çıkan topluluğun bir kısmı, hakarete yakın geri bildirimlerle tüm önerileri öldürdü
Artık Go ekibi bu insanlardan psikolojik olarak çekindiği için hata işleme iyileştirmeleri savaşından vazgeçmiş durumda
Her Go geliştirici anketinde topluluk ezici çoğunlukla hata işlemenin iyileştirilmesine oy veriyor; ama küçük bir aşırılık yanlısı azınlık tüm ilerlemeyi raydan çıkardı
Go, hangi özelliklere ihtiyacın olacağına senin adına karar vereceği yönünde kibirli bir tavır takındı ve işte kullanabileceğin çok az şey sundu
O dönemki tartışmalar:
(130 puan, 148 yorum) https://news.ycombinator.com/item?id=34188528
(748 puan, 544 yorum) https://news.ycombinator.com/item?id=31205072
“Sözdiziminden çok anlambilime önem vermeye başladığım için Zig, Nim, Odin vb. dillere de bakmadım. Artık ‘daha iyi C’ ilgimi çekmiyor” diye bir bölüm var
Yazının epey lafı uzattığını düşünüyorum. Go’nun “tesadüfi” olduğu kısmı saçmalık; çünkü Rust da kökeni ve tasarımı açısından en az onun kadar “tesadüfi”
Gözüme çarpan bir şey, Nim’in kesinlikle “daha iyi C” olmadığı. Garbage collection var, reference counting de kullanabiliyor. İstersen daha iyi C gibi kullanabilirsin
Nim’in tip sistemi, Go’nun sahip olduğu pek çok sorundan kaçınır; ama Rust kadar katı değildir
Sonuçta Go ile çok fazla yazılım yazıldı ve dağıtıldı; hızlı çalışıyor, downtime’ı düşük, genel olarak etkili ve güvenlik sorunları da az görünüyor. Rust ile dağıtılmış yazılım projesinin çok daha az olduğunu düşünüyorum; Firefox da hâlâ %95’ten fazla C++
Bu kavgada bir çıkarım yok; işte Python ve C++’ı memnuniyetle kullanıyorum. Rust ile yazılmış yazılım çok daha az olsa bile, yine de Rust ile çok fazla yazılım yazıldı ve dağıtıldı denebilir. Büyük şirketlerin yatırımları da göz ardı edilemez
0: https://x.com/m_ou_se/status/1599173341117435905
Go’nun neden sürekli Rust ile karşılaştırıldığını anlamıyorum. En uygun karşılaştırma hedefi Java
Go ile Rust karşılaştırmasının daha yaygın ama daha az faydalı olmasının nedeni muhtemelen ikisinin de yeni dil dalgasının parçası olması ve ikisinin de temelde statik linklenmiş binary’ler üretmesi
Java’nın iyi bir seçim olduğu durumlarda Go gerçekten kötü bir seçim. Dilin kendisi sınırlı olmakla kalmıyor, ekosistemi de Java ile karşılaştırıldığında çok sınırlı
Go, C# ve TypeScript’i ana dillerim olarak tutuyorum; bu kombinasyonun harika bir kapsama alanı sunduğunu düşünüyorum. Üretkenlik düşüşünü göze alabileceğim 6 ayım olursa ya da kalite gereksinimleri düşük bir proje çıkarsa Rust’ı ekleyeceğim
Dili öğrenmek 1-2 hafta sürer, ama ekosistem içinde mühendislik yapmayı öğrenmek zaman alır
Performans kaygısının büyük olmadığı çoğu şirket ağ servisleri için C++ kullanmaz. Rust o zamanlar zaten olgun olsaydı iyi bir seçim olurdu; ama baştaki temel sorunlardan biri olan derleme süresi, Rust kod tabanlarında daha da kötü olabilir
Gerçekte de Rust yerine Go kullanılan örnekler gördüm; en büyük neden Go’nun çok daha hızlı derlenmesiydi
Rust ve Go yeterince farklı olduğu için her biri farklı durumlarda mı seçilmeli diye sorarsanız, evet. Zaten bu yüzden ikisi birlikte değerlendirilip biri seçiliyor
Bir zamanlar “daha iyi” bir Python arıyordum. C/C++’tan daha basit ve güvenli ama Python’dan daha hızlı olan, en önemlisi de tek bir binary üretebilen bir dil istiyordum
Bu yüzden Rust’tan Hare gibi daha az bilinen dillere kadar hepsine baktım
Go bariz seçim olmalıydı ama nedenini açıklayamadığım şekilde sözdiziminden hoşlanmadım. Rust’ı anlıyorum. Hatırlaması ve QWERTY olmayan klavyelerde yazması zor çok sayıda özel karakter kullanıyor, başka acı noktaları da var. Çeşitli Lisp’lerde sorun parantezler ve ters Lehçe gösterimdi. Ama Go’dan neden hoşlanmadığımı rasyonelleştiremiyorum
Sonunda Python kodunu Nuitka ile derlemeye karar verdim. Hız artışı var mı bilmiyorum ama artık binary sunabiliyorum
C#’a da giderek daha fazla bakıyorum, çünkü AOT derleme gelişiyor. Yine de varsayılan moddaki laf kalabalığını ve Windows’a fazla bağlı olmasını sevmiyorum
Nim ve Crystal’ı çok beğendim ama küçük toplulukları bir engeldi. Yine de Nim’in bu kadar küçük bir toplulukla başardıklarından gerçekten etkilendim ve onun harika bir dil olduğunu düşünmeye başladım
Bahsettiğim dillerden birini öğrenmek için kendimi motive etmeyi deneyeceğim
Bugünlerde kullanması gerçekten oldukça iyi
C-API’den vazgeçip Go veya Rust gibi dillere köprü kuran başka bir yaklaşım da var
Ben birkaç yıl py2many üzerinde çalıştım. Bu yaklaşımla ilgili geri bildirim almak isterim