Takip et

Go (Golang) ile Başlangıç: Geliştiriciler İçin Pratik Bir Rehber

Go, ya da yaygın bilinen adıyla Golang, Google tarafından geliştirilen, açık kaynaklı ve statik olarak tiplendirilmiş bir programlama dilidir. Yükse…

Go (Golang) ile Başlangıç: Geliştiriciler İçin Pratik Bir Rehber

Go, ya da yaygın bilinen adıyla Golang, Google tarafından geliştirilen, açık kaynaklı ve statik olarak tiplendirilmiş bir programlama dilidir. Yüksek performans, eşzamanlılık desteği ve basit sözdizimi sayesinde modern yazılım geliştirme dünyasında hızla popülerlik kazanmıştır. Özellikle mikroservisler, ağ programlama, bulut tabanlı uygulamalar ve komut satırı araçları geliştirmek isteyenler için ideal bir seçimdir. Bu rehber, Go dünyasına adım atmak isteyen geliştiricilere temel bilgileri sunarak, kurulumdan ileri seviye konulara kadar pratik bir yol haritası çizmeyi hedeflemektedir. Go’nun gücünü keşfetmeye hazır mısınız?

1. Go Neden Bu Kadar Popüler?

Go, geliştiricilere sunduğu benzersiz avantajlar sayesinde kısa sürede büyük bir topluluk edinmiş ve birçok büyük teknoloji şirketi tarafından benimsenmiştir. Bu popülerliğin arkasında yatan temel nedenleri inceleyelim.

Performans ve Hız

Go, derlenmiş bir dil olması nedeniyle C/C++ gibi dillere yakın bir performans sunar. Düşük seviyeli bellek yönetimi ve hızlı derleme süreleri, Go uygulamalarının çok daha verimli çalışmasını sağlar. Özellikle yüksek trafikli sunucular ve performans kritik uygulamalar için Go, mükemmel bir tercihtir. Derleme süresinin kısalığı, geliştirme döngüsünü de hızlandırır.

Eşzamanlılık (Concurrency)

Go’nun en güçlü özelliklerinden biri, dilin çekirdeğine entegre edilmiş eşzamanlılık modelidir. “Goroutine” adı verilen hafif iş parçacıkları ve “kanal” adı verilen iletişim mekanizmaları sayesinde, karmaşık eşzamanlı uygulamalar çok daha kolay ve güvenli bir şekilde yazılabilir. Bu, çok çekirdekli işlemcilerin gücünü tam anlamıyla kullanabilen, ölçeklenebilir sistemler geliştirmek için kritik bir avantajdır.

Basitlik ve Okunabilirlik

Go’nun sözdizimi oldukça sade ve anlaşılırdır. Karmaşık özelliklerden kaçınılması, dilin öğrenme eğrisini kısaltır ve kodun okunabilirliğini artırır. Bu basitlik, özellikle büyük ekiplerde kodun tutarlılığını sağlamaya ve yeni geliştiricilerin projeye hızla adapte olmasına yardımcı olur. Go’nun katı formatlama kuralları (go fmt aracı ile otomatikleştirilir) da kodun her zaman düzenli olmasını garanti eder.

Geniş Kütüphane Desteği

Go, standart kütüphanesiyle ağ, kriptografi, veri yapıları ve I/O işlemleri gibi birçok temel ihtiyacı karşılar. Bunun yanı sıra, geniş ve aktif bir açık kaynak topluluğu sayesinde sürekli büyüyen üçüncü taraf kütüphane ekosistemine sahiptir. Web çerçevelerinden veritabanı sürücülerine, mesaj kuyruklarından makine öğrenimi araçlarına kadar birçok alanda zengin kütüphane seçenekleri mevcuttur.

2. Go Geliştirme Ortamının Kurulumu

Go ile kod yazmaya başlamadan önce, geliştirme ortamınızı kurmanız gerekmektedir. Bu bölüm, Go’nun nasıl indirileceği, kurulacağı ve ortam değişkenlerinin nasıl ayarlanacağı konusunda adım adım rehberlik edecektir.

Go İndirme ve Yükleme

Go’nun resmi web sitesi olan go.dev/dl adresinden işletim sisteminize (Windows, macOS, Linux) uygun kurulum paketini indirebilirsiniz. İndirme işlemi tamamlandıktan sonra, işletim sisteminize özel adımları takip ederek kurulumu gerçekleştirin:

  • Windows: İndirilen .msi dosyasını çalıştırın ve kurulum sihirbazını takip edin.
  • macOS: İndirilen .pkg dosyasını çalıştırın ve adımları izleyin.
  • Linux: İndirilen .tar.gz dosyasını genellikle /usr/local dizinine açmanız ve ardından PATH değişkenini ayarlamanız gerekir. Örneğin:
    sudo rm -rf /usr/local/go
    sudo tar -C /usr/local -xzf go1.22.1.linux-amd64.tar.gz

Ortam Değişkenlerinin Ayarlanması

Kurulumdan sonra, Go komutlarının her yerden çalışabilmesi için PATH ortam değişkeninin ayarlanması gerekebilir. Çoğu otomatik yükleyici bunu sizin için yapar, ancak Linux veya manuel kurulumlarda kontrol etmek önemlidir.

  • Linux/macOS: ~/.bashrc, ~/.zshrc veya ~/.profile dosyanıza aşağıdaki satırı ekleyin:
    export PATH=$PATH:/usr/local/go/bin


    Ardından terminalinizi yeniden başlatın veya source ~/.bashrc (veya kullandığınız dosya) komutunu çalıştırın.

  • Windows: Sistem Özellikleri -> Ortam Değişkenleri'ne gidin ve Path değişkenine Go'nun bin dizinini (örn: C:\Program Files\Go\bin) ekleyin.

Ayrıca, Go modülleri için GOPATH değişkeni eskiden önemliyken, Go 1.11 ve sonrası ile birlikte modüller varsayılan bağımlılık yönetimi haline geldiği için GOPATH'in manuel olarak ayarlanması genellikle gerekmez. Go projeleriniz artık herhangi bir dizinde oluşturulabilir.

Kurulumun Doğrulanması

Kurulumun başarılı olup olmadığını kontrol etmek için terminal veya komut istemcisini açın ve aşağıdaki komutu çalıştırın:

go version

Eğer kurulum başarılıysa, Go'nun yüklü sürümünü gösteren bir çıktı almalısınız, örneğin:

go version go1.22.1 linux/amd64

Bu çıktıyı görüyorsanız, Go geliştirme ortamınız kullanıma hazırdır!

3. Temel Go Sözdizimi ve İlk Programınız

Go'nun temel sözdizimini anlamak, ilk programınızı yazmak için kritik öneme sahiptir. Bu bölümde, "Hello, World!" uygulamasından değişkenlere, kontrol yapılarına ve fonksiyonlara kadar temel Go kavramlarını ele alacağız.

"Hello, World!" Uygulaması

Her programlama dilinde olduğu gibi, Go'ya da "Hello, World!" ile başlayalım. Yeni bir dosya oluşturun (örn: main.go) ve içine aşağıdaki kodu yazın:

package main

import "fmt"

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

Bu kodu çalıştırmak için terminalinizde dosyanın bulunduğu dizine gidin ve aşağıdaki komutu kullanın:

go run main.go

Çıktı olarak "Merhaba, Dünya!" görmelisiniz. Kodu inceleyelim:

  • package main: Her Go programı bir paket içinde olmalıdır. main paketi, çalıştırılabilir uygulamalar için özel bir pakettir.
  • import "fmt": fmt paketi, formatlı I/O (giriş/çıkış) işlemleri için fonksiyonlar sağlar, Println bunlardan biridir.
  • func main(): main fonksiyonu, çalıştırılabilir Go programlarının giriş noktasıdır.
  • fmt.Println("Merhaba, Dünya!"): Ekrana metin yazdırmak için kullanılır.

Değişkenler ve Veri Tipleri

Go'da değişkenler var anahtar kelimesiyle veya kısa bildirim operatörü := ile tanımlanır. Go statik tipli bir dil olmasına rağmen, çoğu zaman tip çıkarımı yapabilir.

package main

import "fmt"

func main() {
    // Tam bildirim
    var ad string = "Ali"
    var yas int = 30

    // Tip çıkarımı ile
    soyad := "Yılmaz"
    boy := 1.75 // float64

    // Birden fazla değişken aynı anda
    var (
        isStudent bool = true
        dersSayisi int = 5
    )

    fmt.Println("Ad:", ad, "Soyad:", soyad, "Yaş:", yas, "Boy:", boy)
    fmt.Println("Öğrenci mi:", isStudent, "Ders Sayısı:", dersSayisi)

    // Sabitler (constants)
    const PI = 3.14159
    fmt.Println("Pi:", PI)
}

Go'nun temel veri tipleri şunlardır:

Tip Açıklama Örnek
bool Mantıksal değerler (true/false) true
int, int8, int16, int32, int64 İmzalı tam sayılar -42, 100
uint, uint8, uint16, uint32, uint64, uintptr İmzasız tam sayılar 0, 255
float32, float64 Kayan noktalı sayılar 3.14, -0.5
complex64, complex128 Karmaşık sayılar 1+2i
string Karakter dizileri "Merhaba"
rune Unicode karakter (int32 alias'ı) 'a', 'ü'
byte 8-bit tam sayı (uint8 alias'ı) 0, 255

Kontrol Yapıları (if, for, switch)

Go'da koşullu ifadeler (if) ve döngüler (for) diğer dillerden farklı bazı özelliklere sahiptir. switch ifadesi ise daha esnek bir yapı sunar.

package main

import "fmt"

func main() {
    // if ifadesi (parantez yok!)
    x := 10
    if x > 5 {
        fmt.Println("x 5'ten büyük.")
    } else if x == 5 {
        fmt.Println("x 5'e eşit.")
    } else {
        fmt.Println("x 5'ten küçük.")
    }

    // if ile kısa bildirim
    if y := 20; y > 15 {
        fmt.Println("y 15'ten büyük ve değeri:", y)
    }

    // for döngüsü (tek döngü yapısı)
    for i := 0; i < 5; i++ {
        fmt.Println("Sayı:", i)
    }

    // while gibi kullanım
    j := 0
    for j < 3 {
        fmt.Println("J:", j)
        j++
    }

    // Sonsuz döngü
    // for { fmt.Println("Sonsuz!") }

    // switch ifadesi
    gun := "Pazartesi"
    switch gun {
    case "Pazartesi":
        fmt.Println("Haftanın ilk günü.")
    case "Cuma", "Cumartesi", "Pazar": // Birden fazla case
        fmt.Println("Hafta sonuna yakın veya hafta sonu.")
    default:
        fmt.Println("Hafta içi bir gün.")
    }

    // switch ile koşullu ifadeler
    sayi := 7
    switch { // switch true
    case sayi < 0:
        fmt.Println("Negatif")
    case sayi % 2 == 0:
        fmt.Println("Çift")
    default:
        fmt.Println("Tek ve pozitif")
    }
}

Fonksiyonlar

Fonksiyonlar, Go'da kodun yeniden kullanılabilirliğini ve modülerliğini sağlayan temel yapılardır. Birden fazla değer döndürebilirler.

package main

import "fmt"

// İki sayıyı toplayan fonksiyon
func topla(a int, b int) int {
    return a + b
}

// Birden fazla değer döndüren fonksiyon
func takas(x, y string) (string, string) {
    return y, x
}

// Parametre tipleri aynı ise kısaltma
func carp(a, b int) int {
    return a * b
}

func main() {
    sonuc := topla(5, 3)
    fmt.Println("Toplam:", sonuc)

    str1, str2 := takas("Merhaba", "Go")
    fmt.Println("Takas sonrası:", str1, str2)

    urun := carp(4, 6)
    fmt.Println("Çarpım:", urun)
}

4. Go Paketleri ve Modülleri

Go'da kod organizasyonu ve bağımlılık yönetimi paketler ve modüller aracılığıyla yapılır. Bu yapılar, büyük projelerin yönetilebilirliğini artırır ve kodun yeniden kullanılabilirliğini teşvik eder.

Paket Kavramı

Go'da her dosya bir pakete aittir. Paketler, ilgili fonksiyonları, tipleri ve değişkenleri bir araya getirir. main paketi, çalıştırılabilir programlar için özeldir. Diğer paketler, bir kütüphane görevi görür ve başka paketler tarafından içe aktarılabilir (import).

Örneğin, bir matematik paketi oluşturalım:

matematik/hesapla.go:

package matematik

// Topla iki sayıyı toplar ve sonucu döndürür.
func Topla(a, b int) int {
    return a + b
}

// Carp iki sayıyı çarpar ve sonucu döndürür.
func Carp(a, b int) int {
    return a * b
}

Not: Go'da dışa aktarılacak (public) fonksiyon, değişken veya tiplerin isimleri büyük harfle başlamalıdır.

main.go:

package main

import (
    "fmt"
    "go_projem/matematik" // Kendi paketimizi import ettik
)

func main() {
    fmt.Println("Toplam:", matematik.Topla(10, 5))
    fmt.Println("Çarpım:", matematik.Carp(4, 7))
}

Go Modülleri ile Bağımlılık Yönetimi

Go modülleri, Go 1.11'den itibaren standart bağımlılık yönetim sistemidir. Projenizin bağımlılıklarını izlemenizi ve yönetmenizi sağlar. Bir Go modülü başlatmak için proje dizininizde aşağıdaki komutu çalıştırın:

go mod init go_projem

Bu komut, go.mod adında bir dosya oluşturacaktır. Bu dosya, projenizin modül yolunu ve bağımlılıklarını (kullandığınız harici paketler) içerir.

Bir harici paket kullandığınızda (örneğin bir web framework'ü), go.mod dosyası otomatik olarak güncellenir. Örneğin:

package main

import (
    "fmt"
    "github.com/gorilla/mux" // Harici bir paket
)

func main() {
    r := mux.NewRouter()
    fmt.Println("Router oluşturuldu:", r)
}

Bu kodu kaydettikten sonra, go run main.go komutunu çalıştırdığınızda Go, github.com/gorilla/mux paketini otomatik olarak indirip go.mod ve go.sum dosyalarını güncelleyecektir.

Kendi Paketinizi Oluşturma

Yukarıdaki örnekte olduğu gibi, kendi paketlerinizi oluşturmak oldukça basittir. Proje dizininizde bir alt dizin (örn: matematik) oluşturun ve içine Go dosyalarınızı (örn: hesapla.go) yerleştirin. Dosyanın en üstünde package matematik bildirimini yapmayı unutmayın. Daha sonra bu paketi, go.mod dosyasında tanımladığınız modül yoluyla (örn: go_projem/matematik) içe aktarabilirsiniz.

5. Hata Yönetimi ve Eşzamanlılık Temelleri

Go, hataları ve eşzamanlılığı ele almak için kendine özgü ve etkili yaklaşımlar sunar. Bu, sağlam ve ölçeklenebilir uygulamalar geliştirmek için hayati öneme sahiptir.

Hata Yönetimi Yaklaşımı

Go'da hata yönetimi, genellikle fonksiyonların son dönüş değeri olarak error tipinde bir değer döndürmesiyle yapılır. Bu yaklaşım, hataların açıkça ele alınmasını zorunlu kılar ve gizli istisnaların önüne geçer.

package main

import (
    "errors"
    "fmt"
)

// Bolme fonksiyonu, sıfıra bölme hatası döndürebilir.
func Bolme(bolunen, bolen float64) (float64, error) {
    if bolen == 0 {
        return 0, errors.New("sıfıra bölme hatası")
    }
    return bolunen / bolen, nil
}

func main() {
    sonuc, err := Bolme(10, 2)
    if err != nil {
        fmt.Println("Hata oluştu:", err)
    } else {
        fmt.Println("Bölme sonucu:", sonuc)
    }

    sonuc2, err2 := Bolme(10, 0)
    if err2 != nil {
        fmt.Println("Hata oluştu:", err2) // Bu çalışacak
    } else {
        fmt.Println("Bölme sonucu:", sonuc2)
    }
}

Go'da panic ve recover de bulunur, ancak bunlar genellikle beklenmedik, kurtarılamaz hatalar için kullanılır ve rutin hata yönetimi için önerilmez.

Goroutine'ler ve Kanallar

Go'nun eşzamanlılık modeli, Goroutine'ler ve Kanallar üzerine kuruludur. Goroutine'ler, çok hafif iş parçacıklarıdır ve bir fonksiyonun önüne go anahtar kelimesi ekleyerek başlatılırlar. Kanallar ise Goroutine'ler arasında güvenli iletişim kurmak için kullanılır.

package main

import (
    "fmt"
    "time"
)

func merhaba(s string) {
    for i := 0; i < 3; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go merhaba("Merhaba Goroutine!") // Goroutine olarak çalıştır
    merhaba("Merhaba Normal!")       // Normal olarak çalıştır

    // Goroutine'lerin bitmesini beklemek için biraz zaman tanıyalım
    time.Sleep(time.Second)
    fmt.Println("Ana fonksiyon bitti.")

    // Kanallar ile iletişim
    mesajlar := make(chan string) // string tipinde bir kanal oluştur

    go func() {
        time.Sleep(500 * time.Millisecond)
        mesajlar <- "Kanal mesajı geldi!" // Kanala mesaj gönder
    }()

    msg := <-mesajlar // Kanaldan mesaj al
    fmt.Println(msg)
}

Bu örnekte, merhaba("Merhaba Goroutine!") fonksiyonu ayrı bir Goroutine olarak çalışırken, merhaba("Merhaba Normal!") ana Goroutine içinde çalışır. Kanallar, Goroutine'ler arasında veri aktarımı için kullanılır ve veri yarışlarını (data races) önler.

Select İfadesi

select ifadesi, birden fazla kanal işlemi üzerinde beklemek için kullanılır. Bir kanaldan veri geldiğinde veya bir kanala veri gönderilebildiğinde ilgili case bloğu çalışır. Bu, eşzamanlı programlamada karmaşık senaryoları yönetmek için güçlü bir araçtır.

package main

import (
    "fmt"
    "time"
)

func main() {
    c1 := make(chan string)
    c2 := make(chan string)

    go func() {
        time.Sleep(1 * time.Second)
        c1 <- "bir"
    }()
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "iki"
    }()

    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-c1:
            fmt.Println("Alındı:", msg1)
        case msg2 := <-c2:
            fmt.Println("Alındı:", msg2)
        case <-time.After(500 * time.Millisecond): // Zaman aşımı
            fmt.Println("Zaman aşımı!")
        }
    }
}

6. Go ile Web Geliştirme ve API Oluşturma

Go, güçlü ağ yetenekleri ve eşzamanlılık desteği sayesinde web servisleri ve API'ler geliştirmek için mükemmel bir platformdur. Standart kütüphanesi bile oldukça yeteneklidir.

Temel HTTP Sunucusu

Go'nun net/http paketi, kolayca HTTP sunucuları oluşturmanıza olanak tanır.

package main

import (
    "fmt"
    "net/http"
)

func merhabaHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Merhaba, Go Web!")
}

func main() {
    http.HandleFunc("/", merhabaHandler) // "/" yolu için merhabaHandler'ı ata
    fmt.Println("Sunucu http://localhost:8080 adresinde çalışıyor...")
    http.ListenAndServe(":8080", nil) // 8080 portunda sunucuyu başlat
}

Bu kodu çalıştırdıktan sonra tarayıcınızdan http://localhost:8080 adresine giderseniz "Merhaba, Go Web!" yazısını görmelisiniz.

Router Kullanımı (Ör: chi, Gorilla Mux)

Daha karmaşık web uygulamaları için, standart kütüphaneden daha gelişmiş bir router kullanmak yaygındır. gorilla/mux veya go-chi/chi gibi popüler kütüphaneler, URL parametrelerini, HTTP metotlarını ve ara yazılımları (middleware) daha iyi yönetmenizi sağlar.

github.com/gorilla/mux ile örnek:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

func anaSayfa(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Ana Sayfa")
}

func kullaniciDetay(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    userID := vars["id"]
    fmt.Fprintf(w, "Kullanıcı ID: %s", userID)
}

func main() {
    r := mux.NewRouter()

    r.HandleFunc("/", anaSayfa).Methods("GET")
    r.HandleFunc("/kullanici/{id}", kullaniciDetay).Methods("GET")

    fmt.Println("Sunucu http://localhost:8080 adresinde çalışıyor...")
    log.Fatal(http.ListenAndServe(":8080", r))
}

Bu örnekte, /kullanici/{id} gibi dinamik yolları tanımlayabilir ve mux.Vars(r) ile URL parametrelerini alabilirsiniz.

JSON API Örneği

Go, JSON verileriyle çalışmak için mükemmel yerleşik desteğe sahiptir. Bu, RESTful API'ler geliştirmek için çok kullanışlıdır.

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
)

type Urun struct {
    ID    string  json:"id"
    Ad    string  json:"ad"
    Fiyat float64 json:"fiyat"
}

var urunler []Urun

func getUrunler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(urunler)
}

func main() {
    urunler = append(urunler, Urun{ID: "1", Ad: "Laptop", Fiyat: 1200.0})
    urunler = append(urunler, Urun{ID: "2", Ad: "Mouse", Fiyat: 25.0})

    http.HandleFunc("/api/urunler", getUrunler).Methods("GET")

    fmt.Println("API sunucusu http://localhost:8080 adresinde çalışıyor...")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Bu basit API örneği, /api/urunler adresine yapılan GET isteğine JSON formatında ürün listesi döndürür. encoding/json paketi, Go yapılarını JSON'a ve JSON'dan Go yapılarına dönüştürmeyi kolaylaştırır.

Sonuç

Go (Golang), modern yazılım geliştirmenin ihtiyaçlarına cevap veren, güçlü, verimli ve öğrenmesi keyifli bir programlama dilidir. Bu rehberde, Go'nun neden popüler olduğunu, geliştirme ortamının nasıl kurulacağını, temel sözdizimini, paket ve modül yönetimini, hata yönetimi ve eşzamanlılık yaklaşımlarını ve web geliştirme ile API oluşturma temellerini ele aldık. Go'nun basitliği, performansı ve eşzamanlılık yetenekleri, onu özellikle mikroservisler, ağ uygulamaları ve bulut tabanlı sistemler için cazip bir seçenek haline getiriyor. Artık Go ile kendi projelerinizi geliştirmeye başlamak için sağlam bir temeliniz var. Unutmayın, pratik yapmak ve Go topluluğuyla etkileşimde bulunmak, bu dili öğrenme sürecinizi hız

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.