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
.msidosyasını çalıştırın ve kurulum sihirbazını takip edin. - macOS: İndirilen
.pkgdosyasını çalıştırın ve adımları izleyin. - Linux: İndirilen
.tar.gzdosyasını genellikle/usr/localdizinine 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,~/.zshrcveya~/.profiledosyanıza aşağıdaki satırı ekleyin:export PATH=$PATH:/usr/local/go/bin
Ardından terminalinizi yeniden başlatın veyasource ~/.bashrc(veya kullandığınız dosya) komutunu çalıştırın. - Windows: Sistem Özellikleri -> Ortam Değişkenleri'ne gidin ve
Pathdeğişkenine Go'nunbindizinini (ö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.mainpaketi, çalıştırılabilir uygulamalar için özel bir pakettir.import "fmt":fmtpaketi, formatlı I/O (giriş/çıkış) işlemleri için fonksiyonlar sağlar,Printlnbunlardan biridir.func main():mainfonksiyonu, ç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) mesajlarBu ö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
selectifadesi, birden fazla kanal işlemi üzerinde beklemek için kullanılır. Bir kanaldan veri geldiğinde veya bir kanala veri gönderilebildiğinde ilgilicasebloğ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) c16. 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/httppaketi, 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:8080adresine 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/muxveyago-chi/chigibi 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/muxile ö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 vemux.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 stringjson:"id"Ad stringjson:"ad"Fiyat float64json:"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/urunleradresine yapılan GET isteğine JSON formatında ürün listesi döndürür.encoding/jsonpaketi, 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
