Özet
2007 yılında Google tarafından tasarlanan Go dili, son yıllarda sunucu ve bulut bazlı uygulamaların da artışı ile oldukça popüler bir programlama dili haline gelmiştir. C ve C++ dilleri gibi derlemeye dayalı bir programlama dili olan Go dili ile Web sunucu yazılımları (back-end), Web API geliştirme, gRPC uygulamaları, komut satırı programları, Kubernetes kullanan yazılımlar gibi pek çok alanda uygulama geliştirme imkanınız bulunmaktadır. Bu kitap da giderek popülerleşen bu dile yeni başlayan kişiler için oldukça güçlü bir başlangıç bilgisi sağlamak amacıyla yazılmıştır. Kitapta sadece dilin söz dizimi özellikleri değil, ayrıca Go dili derleyicisi ile gelen çeşitli araçların kullanımı, Go modülerinin yönetimi, Go standart kütüphanesi, Go ile test yazımı gibi konular da ele alınmaktadır.
İnceleme
Bölüm 1: Setting Up Your Go Environment (Go Ortamınızın Kurulumu)
Bu bölümde öncelikle Go araçlarının ve ortamının nasıl kurulacağından bahsedilmektedir. Go çalışma alanı (workspace) kavramından ve "go" komutundan bahsedilmektedir. Basit bir Go programını bu araçlar ile nasıl çalıştırabileceğiniz gösterilmektedir. "go install" ile üçüncü parti Go araçlarının nasıl indirilebileceği, "go lint" ve "go vet" ile kod formatlama işlemlerinin nasıl gerçekleştirilebileceği kısaca anlatılmaktadır. Go ile geliştirme yapmak için hangi editör veya IDE’yi (Visual Studio Code, GoLand, Go Playground vb.) kullanabileceğiniz anlatılmakta, Makefile’ları kullanarak Go projelerini yönetme gösterilmektedir. Son olarak ise Go araçlarını nasıl güncelleyebileceğinizden bahsedilmektedir.
Bölüm 2: Primitive Types and Declarations (İlkel Türler ve Bildirimler)
Bu bölümde öncelikle Go’da yer alan ilkel türler (primitive types) gösterilmektedir. Sıfır değeri, değişmezler (literals), Boolean türleri, sayısal türler (tam sayı ve kayan noktalı sayı), String’ler, rünler (runes) gibi konulardan bahsedilmekte ve daha sonra bu türler arası dönüşümlerin nasıl yapılacağı kısaca anlatılmaktadır. Daha sonra "var" veya ":=" kullanarak değişken tanımlama gösterilmekte ve bu söz dizimleri arasındaki farklar anlatılmaktadır. Bunun yanında "const" anahtar kelimesinin kullanımı, türlü ve türsüz sabitler, kullanılmayan değişkenlerin durumu, değişkenlere ve sabitlere isim verme gibi konular anlatılarak bölüm sonlandırılmaktadır.
Bölüm 3: Composite Types (Birleşik Türler)
Bu bölümde genel olarak Go’da yer alan şu birleşik türlerden bahsedilmektedir:
- Diziler (arrays)
- Dilimler (slices)
- String’ler
- Rünler (runes)
- Byte’lar
- Map’ler
- Yapılar (structs)
Özellikle dilimlerin özelliklerine fazlaca yer verilmektedir. Dilimlerin uzunluğunu alma, dilimlere eleman ekleme, dilimleri oluşturma, dilimlerin kapasitesini bulma, kendi dilimlerinizi tanımlama, dilimleri içeren dilimler, dilimlerden kopyalama ve dizileri dilimlere dönüştürme gibi konular ele alınmaktadır. Yine kullanıcı tanımlı türleri oluşturmaya yarayan yapılara da giriş yapılmaktadır.
Bölüm 4: Blocks, Shadows, and Control Structures (Bloklar Gölgeler ve Kontrol Yapıları)
Bu bölümde öncelikle Go’da blok (block) kavramına giriş yapılmakta ve değişkenleri gölgeleme (shadowing variables) olayı anlatılmaktadır. Daha sonra "if", "for", "switch" gibi pek çok programlama dilinde yer alan temel kontrol yapıları anlatılmakta, "if" ile "switch" arasındaki farklara değinilmektedir. En son ise "goto" ifadesinden kısaca bahsedilip bölüm sonlandırılmaktadır.
Bölüm 5: Functions (Fonksiyonlar)
Bu bölümde yine her programalama dilinde karşımıza çıkan fonksiyon kavramına değinilmektedir. Go’da fonksiyon tanımlama ve onları çağırma söz dizimi, isimli ve seçeneksel parametreler kullanma, değişken sayıda argüman alan fonksiyonları yazma, birden çok geri dönüş değerine sahip fonksiyonlar yazma, geri dönüş değerini görmezden gelme, isimli geri dönüş değerleri, boş geri dönüş değerleri gibi ayrıntılı konulara yer verilmektedir. Daha sonra ise fonksiyon türünde değişkenler tanımlama ve anonim fonksiyonlar konusu anlatılmaktadır.
Bölümün ilerleyen kısımlarında Closure kavramına girilmektedir. Fonksiyonları başka bir fonksiyona parametre olarak geçme ve fonksiyonlardan fonksiyon geri döndürme konuları anlatılmaktadır. "defer" anahtar kelimesi ile bazı işlemleri fonksiyon bittiğinde gerçekleştirme konusu (yani işlemleri erteleme) ele alınmaktadır. Go’nun temelde değer ile çağırma (call by value) mekaniğini kullanan bir dil olduğundan da bahsedilmektedir.
Bölüm 6: Pointers (Göstericiler)
Bu bölümde öncelikle göstericiler konusuna genel bir bakış atılmaktadır. Göstericilerin ne olduğu ve ne işe yaradığı anlatılmakta, göstericilerden neden korkulmaması gerektiğinden bahsedilmektedir. Göstericiler ile bir fonksiyona parametre olarak geçilen değerlerin, fonksiyon yoluyla kalıcı olarak değiştirilmesi konusu gösterilmektedir. Göstericileri nerede kullanıp nerede kullanmamanız gerektiği anlatılmakta ve bununla ilgili çeşitli örnek senaryolar verilmektedir. Daha sonra göstericiler konusunu da içine katarak Map’ler ve dilimler (slices) arasındaki farklar anlatılmaktadır. Son olarak, Go’da bulunan Garbage Collector mekanizmasınadan ve onun yükünü nasıl azaltabileceğinizden de bahsedilmektedir.
Bölüm 7: Types, Methods, and Interfaces (Türler, Metotlar ve Arayüzler)
Bu bölümde Go’da, tıpkı diğer dillerde yer alan sınıf, yapı gibi söz dizimlerinde olduğu gibi, kullanıcı tanımlı tür bilgilerini nasıl oluşturabileceğimiz gösterilmektedir. Bu türlere çeşitli tiplerden verilerin nasıl eklenebileceği ve kullanabileceği anlatılmaktadır. Daha sonra bu türlerle ilişkili metotları nasıl tanımlayabileceğimiz gösterilmektedir. Gösterici alan ve değer alan metotlar arasındaki farklar gösterilmektedir. Normal fonksiyonlar ile türe ait metotlar arasındaki farklardan da bahsedilmektedir. Ayrıca C’deki numaralandırma (enumeration) türlerine benzer yapıların Go ile nasıl oluşturulabileceği de anlatılmaktadır.
Daha sonra Go’da gömülü alan (embedded field) söz dizimi ile nesne yönelimli programlamada Composition mantığını nasıl programlayabileceğiniz gösterilmektedir. Bunun kaıltımdan farkı anlatılmaktadır. Arayüzler ve tür güvenliği konusuna giriş yapılmaktadır. Arayüzler ile ilgili çeşitli özelliklerden bahsedilmekte, arayüzlerin "nil" ile kullanılması açıklanmakta ve boş arayüzlerin kullanım alanları açıklanmaktadır. Go’da özel bir "switch" yapısı olan Type Switch’lerden bahsedilmekte ve nesnelerin tür bilgilerini nasıl doğrulayabileceğiniz anlatılmaktadır. Bölümün sonlarına doğru Dependency Injection probleminden bahsedilmekte ve bu probleme Go’da örnek verilmektedir. Daha sonra bu problemin çözümünde kullanılan Wire isimli araçtan bahsedilmektedir.
Bölüm 8: Errors (Hatalar)
Bu bölümde öncelikle Go’da hataları nasıl ele alabileceğiniz ile ilgili temel bilgiler verilmektedir. Basit hataları ele almak için String’leri nasıl kullanabileceğiniz gösterilmekte ve bununla ilgili basit bir örnek verilmektedir. Go’da nöbetçi hataları (sentinel errors) adı verilen hatalardan ve bunları nasıl ele alabileceğinizden bahsedilmektedir. Go’da kullanılan hata türleri incelenmektedir. Hataları sarmalama (wrapping errors) tekniklerinden bahsedilmekte ve Go’da hata zinciri (error chain) olarak adlandırılan durumdan bahsedilmektedir.
Hataları farklı biçimlerde ele almayı sağlayan "errors.Is" ve "errors.As" fonksiyonları açıklanmaktadır. Hataları "defer" anahtar kelimesi ile sarmalama gösterilmektedir. "panic" ve "recover" gömülü fonksiyonları ve onların kullanım alanları anlatılmakta, bu fonksiyonlarla ilgili örnekler verilmektedir. Son olarak ise, bir hatadan yığın izleme (stack trace) dökümünü nasıl çıkartabileceğimiz anlatılmaktadır.
Bölüm 9: Modules, Packages, and Imports (Modüller, Paketler ve İthalatlat)
Bu bölümde öncelikle Repo, modül ve paket kavramlarına açıklık getirilmektedir. "go.mod" dosyasının ne olduğu ve içeriği hakkında bilgiler verilmektedir. Daha sonra kendi paketinizi nasıl oluşturabileceğiniz ile ilgili birtakım bilgiler verilmektedir. Bu kısımda verilen bilgiler şu şekilde sıralanabilir:
- “import” ve “export” kavramlarının açıklanması
- Bir paketi oluşturma ve ona erişme
- Paketleri isimlendirme
- Modülünüzü organize etme
- Paket isimlerini ezme (overriding)
- Paket yorumlarını yazma ve “godoc” formatı
- İçsel (internal) paket kavramı
- Paketler için “init” fonksiyonunun kullanımı
- Döngüsel bağımlılıkları ele alma
- Oluşturduğunuz API’yi zarif bir şekilde yeniden isimlendirme ve yeniden organize etme
Bölümün ilerleyen kısımlarında ise modüller ile nasıl çalışabileceğiniz anlatılmaktadır. Üçüncü parti kodları projenize dahil etme, versiyonları ele alma, minimum versiyon seçimi, uyumlu versiyonlara güncelleme, uyumsuz versiyonlara güncelleme ve modülleri dağıtma ile ilgili çok çeşitli bilgiler verilmektedir. Modülleri yayımlama ve versiyonlama ile ilgili ek bilgiler verilip son olarak da modül vekil sunucuları ile ilgili bazı bilgilere değinilmektedir.
Bölüm 10: Concurrency in Go (Go’da Eş Zamanlılık)
Bu bölümde öncelikle Go’nun belki de en önemli özeliklerinden biri olan Goroutine kavramına giriş yapılmaktadır. Go’da Goroutine’leri nasıl yazabileceğiniz gösterilmektedir. Daha sonra Goroutine’ler arası veri alışverişinde kullanılan kanal (channel) kavramına giriş yapılmakta ve kanalların türleri ile ilgili ayrıntılı bilgiler açıklanmaktadır. Kanalları düzgün bir biçimde kullanabilmenize yarayan "select" ifadesi de açıklanmaktadır. Bölümün ilerleyen kısımlarında ise Goroutine’ler ile ilgili örnekler ve tasarım kalıpları gösterilmektedir. Burada gösterilen örnekler ve tasarım kalıpları şöyledir:
- Goroutine’ler, “for” döngüleri, ve değişen değişkenler
- Goroutine’leri her zaman temizlemek
- Done Channel tasarım kalıbı
- Bir Goroutine’i sonlandırmak için “cancel” fonksiyonu kullanmak
- Tamponlu ve tamponsuz kanalların kullanım senaryoları
- Ters basınç (backpressure) kavramı
- “select” ifadesindeki bir durumu kapatmak
- Koda zaman aşımı eklemek
- WaitGroup’ları kullanmak
- Sadece bir kez çalışan Goroutine’ler yazmak
Bir sonraki kısımda ise kanallar yerine Mutex’leri nasıl kullanabileceğiniz, bunu yapmanın avantajları ve dezavantajları anlatılmaktadır. Son olarak ise atomik değişkenlerden çok kısa bahsedilip bölüm sonlandırılmaktadır.
Bölüm 11: The Standard Library (Standart Kütüphane)
Bu bölümde standart kütüphanede yer alan şu paketlerden bahsedilmekte ve kullanım örnekleri verilmektedir:
- io
- time
- encoding/json
- net/http
Bölüm 12: The Context
Bu bölümde Go’da yer alan "context" paketinden ve Context kavramının ne olduğundan bahsedilmektedir. HTTP ile alakalı işlerde Context’leri nasıl kullanabileceğiniz açıklanmaktadır. Ayrıca yine Context kullanılan örneklerde bir hata çıkması sonucu iptal etme (cancellation) denilen sürecin nasıl işlediği anlatılmakta ve örnekler gösterilmektedir. Context’ler ile zamanlayıcıların (timers) birlikte kullanımı açıklanmaktadır. Context’in iptal etme mekanizmasını kendi kodunuza nasıl yerleştirebileceğiniz anlatılmaktadır. Son olarak Context’lerin diğer kullanım alanlarından da bahsedilip bölüm sonlandırılmaktadır.
Bölüm 13: Writing Tests (Testler Yazma)
Bu bölümde Go’da test yazma (birim test) ve test etme sisteminin kullanımı açıklanmaktadır. Öncelikle test etmenin temelleri açıklanmaktadır. Testte ortaya çıkan hataları nasıl raporlayabileceğiniz, testin ana başlatma (setting up) ve sonlandırma (tearing up) fonksiyonlarını nasıl yazabileceğiniz, test verilerini nasıl depolayabileceğiniz, açık (public) API’larınızı nasıl test edebileceğiniz ve "go-cmp" ile test sonuçlarını nasıl karşılaştırabileceğiniz anlatılmaktadır. Test tablosu (table test) isimli test tasarım kalıbından bahsedilmekte ve bununla ilgili bir örnek verilmektedir.
Coverage, Benchmark ve Stub gibi konulardan bahsedilmekte ve Go’da bunları nasıl yapabileceğiniz anlatılmaktadır. "net/http/httptest" paketi ile HTTP ile ilgili karmaşık testleri nasıl yapabileceğiniz gösterilmektedir. Şimdiye kadar anlatılan birim testlerinin yanında, Go’da entegrasyon testlerini nasıl yapabileceğiniz anlatılmakta ve Build etiketleri konusu ele alınmaktadır. Go’nun Race Checker aracı ile eş zamanlılık ile ilgili hataları nasıl saptayabileceğiniz de gösterilmektedir.
Bölüm 14: Here There Be Dragons: Reflect, Unsafe, and Cgo
Bu bölümde Go’da çalışma zamanında tür bilgileri ile çalışmaya yarayan Reflection kavramından, güvensiz bellek erişimi ile ilgili işlerinizi yapmaya yarayan "unsafe" paketinden, C kodlarını Go’da kullanmanıza yarayan Cgo aracından bahsedilmektedir.
Bölüm 15: A Look at the Future: Generics in Go (Geleceğe Bir Bakış: Go’da Genelleyiciler)
Bu bölümde, bu kitap yazılırken henüz Go’ya eklenmemiş bir özellik olan ve C++’taki şablonlara (templates) benzeyen genelleyicilerden (generics) bahsedilmektedir. Genelleyicilerin olası implementasyonları ile ilgili çeşitli bilgiler ve örnekler verilmektedir. Ancak burada verilen bazı bilgiler Go’nun şimdiki genelleyici implementasyonu ile uyuşmadığından bu konuda dikkatli olunması gereklidir.
Değerlendirme
Bu kitabın hedef kitlesi elbette Go diline yeni başlayanlardır diyebiliriz. Ancak "herhangi bir programlama bilgisi olmadan doğrudan Go dili ile programlamaya başlayacak olanlar" için olduğunu düşünmüyorum. Kitapta anlatılanlar en azından bir programlama geçmişinin olmasını gerektiriyor. Derleme, yorumlama, değişkenler, fonksiyonlar, tür bilgisi, multithreading gibi konuları temel anlamda bilerek bu kitabı okumak size daha fazla katkı sağlayacaktır. Kitapta kullanılan dil hedef kitlesi ile uyumlu ve oldukça anlaşılırdır. Kitap Mayıs 2021 tarihinde yayımlandığından, Go’nun o tarihlerdeki 1.15 versiyonu üzerinden anlatım yapılmıştır. Bu nedenle Go’nun en yeni özelliklerini içermemektedir.
Kitapta çok fazla görsel bulunmamaktadır. Zaten programlama kitaplarının genelinde de durum bu şekildedir. Ancak bazı giriş seviyesi programlama kitaplarında bellek ve tür anlatımı yapılırken ve eş zamanlılık ile ilgili özelliklerin gösteriminde daha fazla görsel ve diyagram kullanımını görmüştüm. Bu nedenle bu kitabın görsel ve diyagram kullanımı bir tık yetersizdir diyebiliriz. Ancak bu durum kitabın aktarış kalitesini çok da etkilemiyor.
Kitap kesinlikle eşsiz bir kitap değildir. İnternet üzerinde Go ile iglili pek çok ücretsiz kaynak bulabilirsiniz. Günümüzde Go ile ilgili giriş seviyesinde veya ileri seviyede yazılmış oldukça fazla kitap bulunmaktadır. Bu nedenle aslında bu kitabı eşsizlik yönünden değil de muadillerine kıyasla kalitesi yönünden ele almak gerekir. Kitap içerik anlamında oldukça kalitelidir. Giriş seviyesi bir Go programcısının ihityaç duyduğu hemen hemen her şeyi okuyucuya vermektedir. Bununla da yetinmeyip ek konular (HTTP Client/Server, JSON işleme vb.) ve bazı tasarım kalıpları (Goroutine tasarım kalıpları vb.) ile ilgili de anlatımlar mevcuttur. Ayrıca Go’nun bazı az kullanılan özellikleri ve gelecekte eklenecek (ve hatta eklenmiş) özellikler hakkında da bilgiler vermektedir.
Elbette içerik kalitesinin yanında, içerik ile ilgili tek eleştirebileceğim konu bazı anlatımların ve örneklerin (özelikle araç kullanımlarıyla ilgili gösterilen örneklerin) günümüzdeki versiyonlar ile uyuşmamasıdır. Ancak bu durum çok fazla yerde bulunmamaktadır (son bölüm hariç, orada çok fazla uyumsuzluk bulunmaktadır). Bu nedenle göz ardı edilebilir. Kitap ile ilgili bahsedebileceğimiz bir başka konu da elbette kullanılan örneklerdir. İlk bölümlerde verilen örnekler oldukça anlaşılır ve fazla olsa da ileri bölümlerde örnek sayısı azalmakta ve örneklerin karmaşıklığı artmaktadır. Ayrıca birçok yerde örneğin tam kodu yerine bir kısmı yazıldığından, bazı örnekler biraz anlaşılmaz kalabilmektedir. Yine de genel olarak değerlendirdiğimizde örnek sayısının ve kalitesinin başlangıç seviyesindeki bir kitap için yeterli olduğunu söyleyebiliriz.
Sonuç olarak, programlama ile hali hazırda ilgilenen ve Go diline yeni başlamak isteyen kişilerin bu kitabı okuması onlar için oldukça faydalı olacaktır. Kitabın dili bu kitle için ağır değildir. Kitapta çok fazla görsel ve diyagram bulunmasa da bu durum genel aktarımı etkilememektedir (sadece bazı okuyucular uzun bölümlerden sıkılabilir). Kitap piyasada eşsiz bir kitap olmasa da diğer kitaplara göre anlatım kalitesi ve anlaşılabilirliği yüksektir. Ancak kitapta gösterilen bazı araç kullanımları ve Go dilinin geleceği ile ilgili gösterilen bazı örnekler günümüze göre biraz eski kalmıştır. Bunun dışında özellikle ilk bölümlerde örneklerin sayısı fazla ve karmaşıklığı az iken, ilerleyen bölümlerde ise örnek sayısı az ve karmaşıklığı fazla bir hale gelmektedir.
Learning Go İnceleme Özeti

Basım No: 1st Edition
Yazarlar: Jon Bodner
Yayımlama Tarihi: 28 Mayıs 2021
Sayfa Sayısı: 353
Sonuç Özeti
Sonuç olarak, programlama ile hali hazırda ilgilenen ve Go diline yeni başlamak isteyen kişilerin bu kitabı okuması onlar için oldukça faydalı olacaktır. Kitabın dili bu kitle için ağır değildir. Kitapta çok fazla görsel ve diyagram bulunmasa da bu durum genel aktarımı etkilememektedir (sadece bazı okuyucular uzun bölümlerden sıkılabilir). Kitap piyasada eşsiz bir kitap olmasa da diğer kitaplara göre anlatım kalitesi ve anlaşılabilirliği yüksektir. Ancak kitapta gösterilen bazı araç kullanımları ve Go dilinin geleceği ile ilgili gösterilen bazı örnekler günümüze göre biraz eski kalmıştır. Bunun dışında özellikle ilk bölümlerde örneklerin sayısı fazla ve karmaşıklığı az iken, ilerleyen bölümlerde ise örnek sayısı az ve karmaşıklığı fazla bir hale gelmektedir.




