1 puan yazan GN⁺ 2024-02-08 | 1 yorum | WhatsApp'ta paylaş
  • for döngüsü değişkenleri artık her yinelemede yeniden oluşturuluyor; böylece istemeden paylaşımdan kaynaklanan hataların önüne geçiliyor, ayrıca tamsayılar üzerinde range de mümkün hale geliyor
  • Uyumluluk, Go 1 uyumluluk taahhüdünü koruyor ve neredeyse tüm Go programlarının eskisi gibi derlenip çalışması bekleniyor
  • Çalışma alanlarında go work vendor ile oluşturulan vendor dizini kullanılabiliyor; çalışma alanında vendor varsa -mod=vendor varsayılan oluyor
  • GO111MODULE=off olan legacy GOPATH modunda, modül dışındaki go get desteği kaldırıldı; go build ve go test gibi diğer derleme komutları legacy GOPATH programlarında çalışmaya devam ediyor
  • Runtime artık tür tabanlı GC meta verisini heap nesnelerine daha yakın konumlandırıyor; bu da Go programlarının CPU performansını %1–3 artırıyor ve birçok programda bellek ek yükünü yaklaşık %1 azaltıyor
  • Bazı nesne adresi hizalamaları önceki 16 bayt ve üzeri yerine 8 bayt hizalamaya düşebilir; daha yüksek hizalama varsayan assembly kodunun güncellenmesi gerekir, geçici çözüm olarak GOEXPERIMENT=noallocheaders kullanılabilir
  • PGO derlemeleri artık daha fazla çağrıyı devirtualize edebiliyor; temsili Go programları kümesinde PGO etkinleştirildiğinde çalışma zamanı performansı %2–14 iyileşiyor
  • Standart kütüphaneye ilk v2 paketi olan math/rand/v2 eklendi; Read devralınmıyor, global üretici her durumda rastgele seed alıyor, ChaCha8 ve PCG kaynakları ile N jenerik fonksiyonu sunuluyor
  • net/http.ServeMux yönlendirme desenleri artık method ve wildcard desteği sunuyor; {} içeren desenlerde ve escape edilmiş yol işlemede küçük alt uyumluluk kırılmaları var, GODEBUG=httpmuxgo121=1 ile önceki davranış geri getirilebiliyor
  • crypto/tls sunucusunda varsayılan en düşük sürüm, belirtilmediğinde TLS 1.2 olarak değişti; TLS 1.3 öncesi handshake sürecinde ECDHE içermeyen cipher suite'ler artık varsayılan olarak sunulmuyor
  • Çalıştırma izleyicisi baştan aşağı yenilendi; çoğu platformda OS saatini kullanıyor, akış halinde işlenebilen bölünmüş trace desteği sağlıyor, toplam syscall süresini ve goroutine'in hangi OS thread üzerinde çalıştığını gösteriyor
  • trace aracı web arayüzü, yeni tracer desteği kapsamında güncellendi; Go 1.22 ve sonrası ile derlenen programların trace çıktılarında thread odaklı görünüm ve toplam syscall süresi gösterimi destekleniyor
  • vet, Go 1.22 döngü değişkeni semantiğine uygun olacak şekilde loop closure uyarılarını güncelliyor; ayrıca değersiz append, defer içindeki gecikmesiz time.Since ve log/slog key/value uyumsuzluğu için yeni uyarılar ekleniyor
  • Bootstrap için Go 1.20'nin son point release'i veya daha yenisi gerekiyor; Go 1.24'ün de Go 1.22'nin son point release'i veya daha yenisini gerektirmesi bekleniyor
  • darwin/amd64 üzerinde Go toolchain artık varsayılan olarak PIE üretiyor; Go 1.22, macOS 10.15 Catalina'da çalışan son sürüm olacak ve Go 1.23 için macOS 11 Big Sur veya üzeri gerekecek
  • go/types paketine Alias türü ve Unalias fonksiyonu eklendi; gotypesalias=1 durumunda istemcilerin Alias türünü işlemesi gerekiyor
  • slices.Delete, DeleteFunc, Compact, CompactFunc, Replace artık küçültülen aralıktaki öğeleri zero'lıyor; Insert ise i aralık dışındaysa her zaman panic üretiyor
  • Windows dizin okuma işlevleri artık öğeleri toplu halde okuyarak sistem çağrısı sayısını azaltıyor ve performansı %30'a kadar artırıyor

1 yorum

 
GN⁺ 2024-02-08
Hacker News yorumları
  • Son 3 yıldır ağırlıklı olarak TypeScript kullanıyordum, yakın zamanda Go kullanmaya başladım; başta dizi fonksiyonlarının eksikliği ya da daha az esnek tip sistemi yüzünden biraz endişeliydim.
    Ama 4-5 kişilik bir ekip için TypeScript projesini yeniden kurmayı deneyince, linting, sunucu yönlendirme kütüphanesi seçimi, sunucu seçimi, kodlama standartları, temel hata işleme, iç içe try/catch cehenneminden kaçınmak için özel hata ya da Result tipi dayatmak, test ve mocking, Prisma ayarı gibi şeylere çok fazla zaman gitti.
    TypeScript’i seviyorum ama harika bir standart kütüphanesi, düzgün tip güvenliği ve yerleşik kodlama standartları olan bir dil kullanmak gerçekten rahat. Go’nun da kendine has tuhaflıkları var ama oldukça iyi; routing’in bile standart kütüphaneye girmesi, düşünülmesi gereken bir şeyi daha azalttığı için güzel. Şimdi sadece slice’lar için map/filter/find fonksiyonlarını bekliyorum.

    • CTO bülteninde yakın zamanda TypeScript ve Go sürümleri karşılaştırılmış ve Go 1.22 örnek verilmişti.
      TypeScript her sürümde power user’lar için giderek karmaşıklaşırken, Go tamsayılar üzerinde range gibi eksik kalan şeyleri ekleyerek kullanımı daha basit hale getiriyor.
      Bu, oyun devam yapımlarının ayarları ve mekanikleri sürekli artırıp sonra yeni kullanıcılar için reset gerektirmesine benziyor; programlama dillerinde bunu yapmak zor olduğundan Go’nun bunun farkında olması iyi.
    • Benzer hissediyorum. Beni Go’da tutan şey şaşırtıcı derecede birleşik build toolchain oldu; go:embed ve go:generate ile yapılabilenler, başka projelerde her gördüğümde etkileyici geliyor.
      golang.org/x paketlerinin de neredeyse tüm internet RFC’leriyle ilgili uygulamaları kullanıma hazır şekilde sunması güzel.
    • Slice’lar için map/filter/find gelene kadar lodash’tan ilham alan lo kütüphanesini kullanabilirsiniz.
      Go projelerinde severek kullandığım çok amaçlı araç: https://github.com/samber/lo
    • Özelliğin aşırı fazla olmaması, tersine küçük kararları azaltıyor ve sezgiye aykırı biçimde oldukça üretken kılıyor.
    • TypeScript kullanan bir müşteri için bir süre çalıştım; sonunda buna “Tricks Driven Development” demeye başladım.
      Bir şey yapmak için dokümantasyonu okuyordum, kısa süre sonra biri dokümanlarda olmayan işe yarar bir numarayı söylüyordu; bu sürekli tekrarlandı.
  • Resmî sürüm notları biraz kuru gelirse, interaktif bir sürüm hazırladım: https://antonz.org/go-1-22

    • for döngüsü değişkeninin paylaşılması sorunu başta hemen anlaşılmamıştı; kendim çalıştırıp beklenmedik sonucu görmek yardımcı oldu.
    • Compact ve Replace örnekleri kafa karıştırıcı; bunun doğru olup olmadığını bilmiyorum.
  • Go’yu 9 yıldan uzun süredir kullanıyorum; son 4 yıldır Flutter yüzünden Dart’ı da çok kullandım ve bence iki dilin karmaşıklığa yaklaşımı taban tabana zıt. Dart mümkün olan her özelliği eklemeye çalışıyor, Go ise bunun tersi.
    Birincisi, Dart’ta bir sınıf içinde değerleri başlatmanın o kadar çok yolu var ki buna çok zaman harcanıyor. final/const/static/late öneklerine göre constructor, factory, Flutter StatefulWidget’ının initState()’i gibi başlatma yerleri değişiyor; refactoring yapınca başlatmayı ciddi biçimde elden geçirmek gerekiyor. Fonksiyon gibi davranan getter’lar da yeni codebase’lerde kafa karışıklığını artırıyor.
    İkincisi, Dart’ta map, stream vb. tek satıra sıkıştırmaya uygun çok özellik var; bu da anlaşılması zor tek satırlık kodları hızla yazma isteği doğuruyor. Ama debug ederken ya da junior geliştiriciler firstWhereOrNull gibi hack’lerle ve orElse: () => null gibi opsiyonel parametrelerle karşılaştığında çok karışıyor. Anlaşılması güç null safety ya da tip hataları da sık sık yolu kesiyor; bunları basit Go tarzı bir for döngüsüne çevirmek gerçekten rahatlatıyor.

    • Dart için bir ipucu: UI ile doğrudan ilgili olmayan işler için initState kullanmamak iyi olur. Örneğin bir metin alanı ipucunu ayarlamak gibi bir şey değilse kaçınmayı tercih ederim.
      Çoğu Flutter sayfasının yapacak çok az işi olur; ya da parent bir MyPageController nesnesi oluşturur, istediği şekilde başlatır ve child sayfanın o controller’a göre davranmasını sağlar. Örneğin bir liste sayfasında kullanıcı bir öğeyi düzenlemek istediğinde controller oluşturup öğeyi içine koyarak child sayfaya gönderirseniz, geri dönüldükten sonra parent controller’daki öğeye veya değişkenlere/callback’lere bakıp UI değişikliğine karar verebilir.
      Böylece InheritedWidget gibi şeylere dokunmadan widget’lar arası etkileşimi ince ayrıntıda kontrol edebilirsiniz. Elbette bunu bir state management kütüphanesiyle kullanmak iyi olur, ama pratikte kullanılmadığı durumlar da çok.
    • Go’nun en büyük avantajının basitlik olduğu konusunda katılıyorum. range de aynı şekilde; sonuçta yazılan karakter sayısı forEach(f) gibi comprehension’lara benzer olsa da üç satıra yayıldığı için daha uzun görünür, ama açıp yazınca büyük bir mesele değildir.
      Yine de başlatma konusunda Go’da struct alanlarını belirli bir değere başlatmanın idiomatik bir yolu olmasını isterdim. Constructor olmaması sorun değil ama bazen bir bool’un varsayılan olarak true başlatılmasını istediğim oluyor.
    • initState, StatefulWidget’ın override’ıdır ve diğer framework’lerdeki lifecycle event’lerinden farklı değildir; Flutter tarafına ait bir kavramdır, constructor ile karıştırılacak nitelikte değildir.
      Normal constructor ile factory’den hangisini kullanmak gerektiği kafa karıştırabilir ama initState yüzünden Go’nun üstün olduğunu söylemek zor.
    • Pahalı uzmanların birbirleriyle özlü biçimde iletişim kurabilme yeteneğini optimize etmek gerekir. Güçlü sözdizimi araçlarını acemilerin elinden almak, onların uzmanlık geliştirmesini engellemekten başka işe yaramaz.
  • io.Copy, TCPConn’dan UnixConn’a kopyalarken mümkünse Linux’un splice(2) sistem çağrısını kullanıyor ve yeni TCPConn.WriteTo metodundan yararlanıyor.
    Interface upgrade’iyle bir kez daha şeffaf biçimde zero-copy I/O artmış oluyor. io paketinde bu desenle elde edilen etki gerçekten büyük.

    • Go standart kütüphanesinde bu tür ayarlamalardan gerçekten çok var. Mutlaka kötü değil, ama bu tür özel işlemler ölçeklenebilir olmadığı için standart dışı kütüphanelerle entegrasyon daha az tatmin edici hale geliyor.
      Yine de beklenen sınırlar içinde.
  • Geliştirilmiş yönlendirme desenleri, Gorilla Mux’un geleceğinin belirsiz olduğu şu dönemde iyi bir iyileştirme
    Ancak bu değişiklik küçük bir şekilde geriye dönük uyumluluğu bozuyor; { ve } içeren desenlerin davranışının değişmesi gibi açık kısımlar da var, kaçışlanmış yolların işlenmesi gibi daha az belirgin kısımlar da. GODEBUG içindeki httpmuxgo121 alanıyla kontrol ediliyor; httpmuxgo121=1 ayarlanırsa eski davranışa dönülebiliyor
    Ama “Go 1 belirtimine göre yazılmış programlar, bu belirtimin ömrü boyunca değişiklik olmadan derlenmeye ve doğru çalışmaya devam eder” diyen Go 1 uyumluluk vaadi ile neden çelişmediğini merak ediyorum

    • Go 1 uyumluluk vaadini aşmanın yolu, bu tür geriye dönük uyumsuz değişiklikleri go.mod içindeki go yönergesi değerine bağlamak
      1.22 veya üzeriyse yeni kütüphane davranışını alıyorsun, değilse eski davranışı. Pratikte ne kadar iyi işleyeceğini görmek gerekecek
    • Go ekibi genelde bir şeyi bozmadan önce GitHub’ı ve açık kaynak programları tarayıp insanların nasıl kullandığına bakar. Muhtemelen HTTP handler yollarında { ve } kullanımının çok nadir olduğunu görmüşlerdir
      Yeni davranışı kapatmanın bir yolunu da sunuyorlar, yani kod değişikliğini zorunlu kılmıyorlar; yine de yeni bir ortam değişkeni ayarlamak gerekiyor
      Bu sürümdeki for döngüsü semantiği değişikliği de benzer bir örnek; fiilen bozucu bir değişiklik. Yine de tüm Go programları derlenmeye ve çalışmaya devam ediyor, yalnızca bazı davranışlar biraz değişiyor. Go’nun pragmatik bir yaklaşım seçtiğini düşünüyorum; bu da başarı nedenlerinden biriydi
    • Bence bu Go’da nadir görülen bir hata. Sürüm bazında bozmak için go.mod kullanılacaksa, en azından daha iyi bir şekilde bozmalı
      go.mod 1.22’ye değiştirildiğinde incelikli çalışma zamanı sorunlarını bulmaya çalışmaktansa, kodun derlenememesi çok daha iyi olurdu
    • Aksi halde kısa ve güçlü reklam cümlesini kaybedersin. Küçük olsun ya da olmasın, bu uyumsuz bir değişiklik
  • Go 1.22’de döngünün her yinelemesi yeni bir değişken oluşturuyor
    Bu konu burada daha önce de tartışılmıştı: https://news.ycombinator.com/item?id=33160236 - Go: Redefining For Loop Variable Semantics (2022)

  • Eski kafalı olabilirim ama fonksiyonlar üzerinde range eklenmesini sevmiyorum. Dile eklenen karmaşıklığı haklı çıkaracak kadar büyük bir kolaylık sağlamıyor; fonksiyonel tarz da Go’nun açık, imperatif, lafı uzun ama az özellikli tarzıyla uyumsuz görünüyor. Bence bu, Go’nun büyük avantajlarından biriydi
    Aynı nedenle tamsayılar üzerinde range de yanlış yönde bir adım gibi geliyor. Go’nun ince özellik seti ve düşük bilişsel yükü her zaman başlıca güçlü yanı ve ayırt edici özelliğiydi

    • Şu an bu özellik isteğe bağlı ve deneysel; açıkça etkinleştirmek gerekiyor. Standart olarak açılacaksa, yaygın kullanılmaması gereken durumlarda geliştiricileri kullanmamaya yönlendirecek bir kapatma mekanizması olmasını isterim
      Yazılım geliştirmedeki büyük sorunlardan biri, geliştiricilerin karmaşıklık eklemesini veya yetenek gösterisi yapmasını engellemek. Özellikle kariyerinin başındaki geliştiriciler, sorunu doğrudan ama daha az zarif ve daha uzun bir şekilde çözüp geçmek yerine, çözümü aşırı karmaşıklaştırma eğiliminde oluyor
    • Bu özellik için henüz erken gibi. İdeal olarak lambdalar ve generic parametre paketleri geldikten sonra eklenmeliydi
      Go’nun mevcut generics desteği bunu taşıyacak kadar gelişmiş değil; bu yüzden tuhaf şekilde zorlanmış kısıtlar ortaya çıkıyor
    • Ben de kararsızım. Inline fonksiyon geçmeye kıyasla kod satırı sayısını azaltmayabilir bile
  • sql.Null[T] eklenmesi iyi olmuş. Yeni projelerde muhtemelen kullanmaya başlarım
    Şu anki işimde API’si oldukça benzer olan sqlboiler’ın null [0] paketine bağımlıyım. sql.Null gibi davranıyor ama değerin açıkça hiç ayarlanıp ayarlanmadığını söyleyen ek bir IsSet() bool metodu var; bu da “bilerek null” ile “başlatılmadığı için null” ayrımına yardımcı oluyor. İyi görünüyor ama pratikte hiç kullanmadım

    • Null’un ne zaman bilinçli olduğunu neden bilmek gerektiğini merak ediyorum. Veritabanında buna karşılık gelen bir tip yok, değil mi
  • Standart kütüphane mux’una yeniden bakıp chi’yi kaldırmanın da mümkün olup olmayacağını merak ediyorum. Böyle özelliklerin standart kütüphaneye girmesi gerçekten güzel

    • Ben de tam bunu söylemeye gelmiştim. chi birkaç projede gerçekten harikaydı; hatta varlığını unutturacak kadar doğal çalışıyordu
      Bu tür özellikler standart kütüphaneye girince her zaman bakımı yapılmış oluyor ve birçok Go programında aynı yaklaşımın kullanılmasını sağlıyor
  • Go’yu production’da kullananlar en yeni sürüme hızlıca geçebiliyor mu, yoksa eski sürümlere mi bağlı kalıyor, merak ediyorum
    Açık projelere bakınca nispeten yeni özelliklerden çoğu zaman kaçınılıyor gibi görünüyor. Generics kullanmasam bile eski interface{} yerine Go 1.18’de gelen any kullanmak istiyorum; ikincisinin daha “idiomatic” olduğu da söyleniyor

    • Square’de genellikle Go monorepo’sunun varsayılan sürümünü yükseltmeden önce ilk nokta sürümünü bekleriz. Tekil uygulama sahipleri daha erken yükseltebilir
      Bu sefer biraz karıştı; biz varsayılanı 1.21’e yükseltmeden Go ekibi 1.22’yi çıkardı. Artık beklemek neredeyse bir teamül gibi; Go sürümlerinin bir şeyleri bozması nadirdir
    • Yeni özellikleri, onlara gerçekten uyan bir problem görene kadar denemeyi bekleme eğilimindeyiz; ama derleyici sürümünü sürüm çıktıktan hemen sonra neredeyse anında yükseltiyoruz
      Örneğin generics’i gerçekten kullanmadan önce yaklaşık 6 ay bekledik; kullanışlılığı, geliştirici deneyimini ve derleme/test hızı etkisinin büyük olmadığını kontrol ettik
    • İş yerinde production’da çalışan container’lar, yani SaaS/API servisleri için geliştiriciler en yeni build’e serbestçe geçebiliyor
      Ama Go ile son kullanıcı uygulamaları da sunuyoruz; bu tarafta eski istemci işletim sistemleriyle uyumluluk nedeniyle 1.20’de kalmamız gerekiyor. 1.21’de önemli bir kesinti olduğu için muhtemelen birkaç yıl 1.20’de kalacağız
    • CI, Go’nun latest container’ı ile build ve test yapıyor; test paketi de oldukça sağlam olduğu için fiilen otomatik güncelleniyoruz. Bir şey uymazsa pipeline kırılıyor; o noktada son çalışan sürüme sabitlemeye mi yoksa bozucu değişiklik düzeltilene kadar güncellemeyi ertelemeye mi karar veriyoruz
      Birkaç yılda bir yeni sürüm ile üçüncü taraf paketler arasında ince bir edge-case bug ortaya çıkabiliyor; ama böyle bir bug tanımı gereği test paketinden kaçmış olduğundan, manuel yükseltme yapsaydık da muhtemelen yakalayamazdık
    • Hemen geçiyoruz
      Eski Go derleyicilerini desteklemekten endişeleniyorsan, eski sürümler için build koşulları koyup eksik olanları tanımlayabilirsin. Örneğin // +build !go1.7 altında type any = interface{} koyabilirsin