in Go

Go Programlama Dili Üzerine

İlk defa Postfix’in kuyruklama istatistiklerini self-hosted çalışan ve raporlayan bir sistem tasarlarken Go’yu keşfetmiştim.
İçindeki net/http paketi’, template yapısı ve hızı direk karar vermemi sağladı. Bir öğleden sonrada oturup syntax’i çözüp direk bodozlama kodlamaya başladım. Sonra lazım olan her yerde basit yazılan bu dili, script dili niyetine kullanırken buldum kendimi.
En son Netdirekt‘den Semih‘in gazlaması “Production’da da Go kullansak mı?” diye ciddi ciddi düşünür oldum ve şimdi MaestroPanel’in bir çok yerinde kullanıyoruz.
Ha! Bu arada bir projeyi yine Go ile kotarıp ilk paramı kazanınca böyle bir yazı yazmayı kendime bir borç bildim.

Go’ya direkt balıklama dalmak istersen http://tour.golang.org/welcome/1 adresinden devam edebilirsin.

Kim? Ne? Nasıl?

Go 28 Mart 2012’de version 1’e ulaşmış fakat ilk piyasada görülmesi 2009’a dayanıyor. Ken Thompson, Rob Pike ve Robert Griesiemer gibi babaların emeği var, alın teri var. Bu veteranlar eski Bell‘ciler (Bellci dedim yahu! :) Unix işletim sistemi, C programlama dili, Plan9 ve UTF8’i bu abiler tasarladı hep. E tabi adamlarda tecrübe gırla, ek olarak Google’ın “Herkesden Farklı Yap” mantığı ile birleşince Go garipliği çıkmış ortaya.

Go takımı ile tanışmak isterseniz bu videoyu izleyebilirsiniz

Go’da ilk fark edeceğiniz şey basitlik. Bildiğin JavaScript gibi C muadili bir dil ile güle oynaya yazıyorsunuz. Pazarlamasıda buna göre kurulmuş Go’nun. Dokumanlarına göz atarsanız da sürekli “C gibi ama daha basit” cümlelerin çokluğunu farkerdersiniz.

Elinizi kod’a bulaştırdığınız zaman ilk derlediğinizde derlenmedi sanıyorsunuz. Halbuki öyle çabuk derleniyorki sabahlar olmasın.

Şekil

Go yazanlar kendilerine gopher diyorlar, ilk duyduğumda hani eski protokol olan gopher sandımdı ama meğerse gopher diye bir hayvan varmış. Logoyu bu hayvandan esinlenerek Renee French tasarlamış. Buradan Go maskotunun hikayesini okuyabilirsiniz.

Go Logosu

Buradan tüm gopher imajlarını bulabileceğiniz içeriğe ulaşabilisiniz.

Un-Googleable

Un-Googleable’da neymiş reyiz? Ben de Go’ya bulaşmadan önce bilmiyordum ama Go Google’ın geliştirdiği bir dil olmasın rağmen Google’da Go diye aratamıyorsunuz doğal olarak. Bunun yerine Golang veya Go programming diye aratmanız gerekiyor. Domain “golang” yani.

Güncelleme 17.4.2017
Artık Google’da “go” aratılınca ilk sıralarda çıkıyor. (Teşekkürler Eren)

Açık Kaynak, Cross-Platform

Go, tamamen açık kaynak. Github’a yerleşmiş github.com/golang. Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD,Windows, Plan 9 (hiç görmedim bile) işletim sistemlerini destekliyor.
Her sisteme göre ayrı derlemen gerekiyor ama bağımlılık olmaması ve kendi runtime’ı içinde gelmesi, tek dosyada olayı bitirmesi tam istediğim basitlikti, buradan tav olduğumu söyleyebilirim sanırım. Update’ler sadece tek dosyanın değişmesi ile mümkün oluyor. Temiz.

Bağımlılık istememesi güzel fakat şöyle bir gariplik oluyor. Tüm paketleri tek bir dosya içinde tuttuğu için derlediğinizde projenin durumuna göre output  alışılmışın dışında büyük oluyor. Örneğin orta ölçekli bir web servisi yazdığınızda veritabanı, http ve I/O paketleri ile beraber 15MB’a civarı output veriyor.

Cross Platform demişken Go’nun Mobile tarafınada değinmek lazım hafiften. Go 1.4 sürümünden sonra golang.org/x/mobile/app paketini import ettiğinizde Android üzerinde logic oluşturabiliyorsunuz, zamanla IOS desteğide gelecek akabinde Windows planlarının arasında. Hatta elemanın biri IOS’a port etmiş bile.

Daha fazla bilgi almak için aşağıdaki sunum’a ve videosuna bakabilirsiniz.

Bu arada Go’nun Mobile tarafına baktığınızda. Contributor’lerde Burcu Doğan‘ın göreceksiniz. Türkiye Go camiası için güzel bir haber.

Object-Orient?

Dil, hem Object Orient hem değil, hem de Type Safety ama aynı zamanda Dynamic-Typing özelliklerini taşıyabiliyor. Object-Orient şeklinde method ve fonksiyonları yönetebilmenize rağmen Java veya C#’daki geleneksel bir OOP beklemeyin. Daha ilkel.

Inheritance akabinde Polymorphism Go’da biraz alışılmışın dışında. Go’da tip hiyerarşisi bulunmuyor, yani tüm tip’ler primitif bir Object tipiden türemiyor. Tabi adamlar spor olsun diye böyle yapmamış. Hiyerarşi geleneksel OOP’de overused yarattığı için tercih etmemişler. En azından fikirleri bu yönde.

Bu konu çok derin ve baya tartışmalı. Bağlantılar genel bir fikir verir.

Neye Benziyor?

Go’yu ilk gören developer “La olum bu Pascal’a benziyor” yok yok “C’ye benziyor” geyiklerini yapıyor. Go’yu geliştirenler burada o soruyu yanıtlamış (Genelde C’ye beziyor ama Pascal/Modula/Oberon’dan ve Limbo’dan esinlendik diyorlar. Eyvallah.) (Limbo diye programlama dili varmış öğrenmiş olduk.)

Temelde gerçekten okunması kolay bir dil. Tecrübeli biri Cumartesi öğleden sonrasını ayırsa yeterli. Aşağıdaki Hello World’e bakın hele.

package main

import "fmt"

func main() {
    fmt.Println("Merhaba Dünya")
}

Açıklamaya girmeyeceğim. Temiz!

Public ve Private işaretlemeleri de büyük espiri! Örneğin değişken isimleri küçük harf ile başlıyorsa “private“, büyük harf ile başlıyorsa “public” olarak belirleniyor.

Değişken tanımlamalarıda aşina olduğumuz şekilde;

var x int

veya

var x = 500

veya

x := 500

gibi kullanabilirsiniz. Birinci örnek static type gibi, ikiciside dinamik. Son örnek := tanımlaması sadece fonksiyonlar içinde kullanılabiliyor, fakat genelde daha önce tanımladığınız err isiminde değişkeni yeniden tanımlayamazsın hatasına neden oluyor, sık sık (en azından benim yoğurt yiyişim böyle)

Birde multi-valued hadisesi var. Bir fonksiyondan birden fazla sonuç dönebiliyorsunuz. Çok kullanışlı. Örneğin aşağıdaki fonksiyon int ve bool dönüyor.

func Islemler(x, y, z int) (int, bool) {
    var a int = x + y + z
    b := 20 < a
    return a, b
}
islem, durum = Islemler(1,2,3)
Sınıflar (Struct)

Go’da Class’a Struct deniyor. Ne kadar OOP temelli olsada Go’da tam bir class yapısı bulunmuyor. Struct üzerinde inheritance, method ve fonksiyon ekleyip, field’ları private, public işaretleyebiliyorsunuz, interface’ler uygulayabiliyorsunuz tabi.

Tip aşağıdaki şekilde oluşturuluyor;

type Hayvanat struct {
    Yas int
    Isim string
    Ayakata bool
}

Cümle içinde kullanmak gerekirse, değer tanımlamaları aşağıdaki gibi yapılıyor.

x := Hayvanat{
    Yas: 5,
    Isim: "Kopek",
    Ayakta: true
}
Paket Yönetimi

Go paket yönetimini gayet iyi çözmüş. GOPATH\src klasörünün içine direkt source kodu atıp uygulamanızdan çağırabiliyorsunuz. Paket ve bağımlılık yönetimi için go komutunun get parametresinden yürüyoruz. Bu araç ile ister gibhub’dan ister başka source control alanından paket ve bağımlılık edinebiliyorsunuz. Go ile gelen bir çok özellik paket şekilde geliyor zaten.

Örneğin projemize Cal-Dav ile ilgili bir client olan caldav-go‘yu ekleyeceğiz. Çalıştırmamız gereken komut aşağıdaki gibi;

go get github.com/taviti/caldav-go

daha sonra projenize import edebiliyorsunuz. Bu kadar!

Go’da yeniden kullanılabilir paketlerinizi nasıl oluşturabileceğinizi anlatan bir yazıda burada paylaşayım. Ek Bu da güzel.

Cross Platform demişken ARM (RaspberryPi) , arm64, Android ve 1.5 sürümünden sonra IOS’da dahil go ile kod yazabileceğinizi belirteyim.

Kafanızda başka sorular varsa Sık Sorulan Sorulara göz atmanızı tavsiye ederim https://golang.org/doc/faq

Generics

Generics yok! Çok performanslı çalışan bir modelini bulmadıkça da eklemeyi düşünmüyorlarmış. Benimde ilk başta sorduğum soruydu. Kısaca dili yavaşlatır diye eklememişler şimdilik. Go topluluğunda bunun üzerine çok tartışma dönüyor. Yaz geç arkadaşım.

Yaz geç ama Generics olmayınca Type meselesi biraz zahmetli oluyor. Interface{} ile beraber kendi çapında bir kolaylık sağlamasına rağmen polymorphism’ın desteklenmeyişi bir çok kod ameleliğine neden olabiliyor. Özellikle Interface{} parametresi alan fonksiyonlar aşağıdaki gibi bir sorun çıkıyor.

type Topla interface{}
func Nerede(x Topla) Topla {
// x.(type) = ?
}

Örneğin x’in tipini bulmak için benim oraya bir ton switch case’i koymam gerekiyor. Bu hem error handling’i zorlaştırıyor hem de fonksiyon içindeki bir çok runtime hatasına gebe bir durum oluşturuyor.

Go’daki bu handikap’a verilen vevap ise Rust Programlama Dili oluyor. Rust’da fena değil hani.

Bu arada overloading’de yok. Why does Go not support overloading of methods and operators?

Error Handling

Error Handling Yok! Var ama çok eziyet :) Genelde hata yakalamak için kullanılan try-catch-finally blokları yerine Multi-Value ile fonksiyonların geri dönüşünde Error tipi döndürlüyor.
Bunun nedenide try-catch-finally bloklarının iç içe geçerek bir kod düğümü oluşturması sonucu performans kaybı.
Go biraz farklı yaklaşmış konuya. Multi-Value özelliğini kullanarak hatalar her bir fonksiyonun sonucu olarak dönüyor ve her fonksiyondan sonra error handling yapmak zorunda kalıyorsunuz.

İncelemek isterseniz buradan devam edin.

Bunun sonucunda her yer if err != nil  koşulları ile doluyor. Bazı durumlarda da hata yakalayacağım diye Printf maymununa dönüldüğünde oluyor. Ben döndüm mesela.

Error handling ile alakalı yine built-in gelen panic ve recover özelliklerin incelemenizi öneririm.

Concurrency

Go’da native olarak Concurrency desteği vardır. Genelde klişe şudur “C  gibi ama concurrency kullanabiliyorsun, süper olum”.

Go’da gerçekten iyi tasarlanmış bir Concurrency mimarisi var, yani aynı anda birden fazla fonksiyonu paralel çalıştırabilir, bunların durumlarını channel denen şey ile sorgulayabilirsiniz. İşletim sistemi seviyesinde olmadığından çok az maliyetli bir ton goroutine çalıştırabilirsiniz.

Go’nun söz diziminde Concurrency fonksiyon tanımlamak harbi büyük espiri. Eminim dili tasarlayanlar böyle yapalım dedikten sonra bira içerken sağlam gülmüşlerdir. Aşağıdaki fonksiyona bir bak.

func Pingle(ipaddr string) {
   go func() {
       //İşlemler yapılır
   }
}

Go’da async bir foksiyon başlatmak için f() olan fonksiyonu go f() ile async yapabiliyorsunuz C#’da await gibi bir şeye tekabul ediyor. Go’da ise goroutin deniyor. fikir vermesi açısında örneğe bir göz atın derim.

Goroutin  güzelliği, oluşturduğunuzda işletim sisteminde yeni bir thread açmadan onlarca goroutin’i çok az maliyet ile başlatabiliyorsunuz. Bu hafif thread’ler programatik olarak bir delta’da koşuyor fakat belirli bir algoritmaya göre işletim sistemi üzerinde ayrı bir thread’e geçiyor. (TODO: Not! Bu konuyu daha derinlemesine öğren.)

Son olarak mesajımı veriyorum. Concurrency is not parallelism.

Test

Tabiki Go’da TDD yürüyebiliyorsunuz. Hatta debug çok sıkıntılı olduğundan test’le gitmeniz şart gibi. Go’daki test ile aynı zamanda dokümantasyonuda kotarıyorsunuz.

Şöyle;

Godoc komutu uygulamanızdaki test ve fonksiyonları analiz ederek standart bir dokümantayon çıkartılmasını sağlıyor. Bunu yaparkende test’leri izliyor ve hemen çalıştırılabilir canlı bir dokümantasyona kavuşuyorsunuz.

Test’e tekrar geri dönersek;

Go’da entegre bir test kütüphanesi var. Bu paketi kullanarak testleri yazıyorsunuz. Test için dosyanın sonu *_test.go olarak bitmesi gerekli. “go test” bu dosyaları anlayıp çalıştırıyor.

Öreğin;

package testlestir
  import "testing"
  func GeriCevriliyorMu(t *testing.T){
       if strings.Reverse("maestropanel") != "lenaportseam"{
          t.Error("Patladı")
       }
  }

Çıktısı ise FAIL veya PASS olarak dönüyor. Temiz basit. (Çok test olduğunda Go console’u yetmiyor daha görel bir şeylere gereksinim duyuyorsunuz.)

Tabi developer hep daha kolayını arar durur. Testify diye bir proje var bunuda kullanabilirsiniz. Bildiğimiz assert.Equal() rahatlığında koşul vermenizi sağlıyor.

Bonus:

Go Programlama Dilinde Unit Test

Kitap, İçerik, Kaynak

 

 

Yorum Bırak

Comment

  1. Eline sağlık. Compiled dil ile yazılan web uygulaması, script dillerle yazılanlardan epey daha hızlı olsa gerek.

  2. Go dilini tanıtmak adına güzel bir yazı olmuş teşekkürler. (dipnot: go kelimesi googleda aratılınca ilk sıralarda dilin kendi sitesi çıkıyor.)

Webmentions

  • Golang Notları 002 - gurmezin sci-tech-art 15/05/2017

    […] http://blog.oguzhan.info/?p=870 […]

  • Go (Golang) | Pearltrees 15/05/2017

    […] Golang Üzerine – Oğuzhan Blog. İlk defa Postfix’in kuyruklama istatistiklerini self-hosted çalışan ve raporlayan bir sistem tasarlarken Go’yu keşfetmiştim. İçindeki net/http paketi’, template yapısı ve hızı direk karar vermemi sağladı. Bir öğleden sonrada oturup syntax’i çözüp direk bodozlama kodlamaya başladım. Sonra lazım olan her yerde basit yazılan bu dili, script dili niyetine kullanırken buldum kendimi. En son Netdirekt‘den Semih‘in gazlaması “Production’da da Go kullansak mı?” Diye ciddi ciddi düşünür oldum ve şimdi MaestroPanel’in bir çok yerinde kullanıyoruz.Ha! Bu arada bir projeyi yine Go ile kotarıp ilk paramı kazanınca böyle bir yazı yazmayı kendime bir borç bildim. Go’ya direkt balıklama dalmak istersen adresinden devam edebilirsin. […]

  • Go (GoLang) Programlama Dili Maceram - Murat Özalp 15/05/2017

    […] http://blog.oguzhan.info/?p=870 […]