Go, Google'ın 2009'da duyurduğu, derlenen ve statik olarak bağlanan bir programlama dili. Sistem yöneticileri ve DevOps ekipleri için özellikle çekici olmasının nedeni basit: yazdığınız kod tek bir çalıştırılabilir dosyaya derleniyor, o dosyayı sunucuya kopyaladığınızda yanında ne yorumlayıcı ne de bir sürü paylaşımlı kütüphane taşımanız gerekiyor. Docker, Kubernetes, Prometheus, Terraform, Caddy gibi bugün altyapının temelini oluşturan araçların hepsi Go ile yazıldı. Bu yüzden sunucunuzda Go'yu doğru kurmak, hem kendi küçük araçlarınızı yazmak hem de kaynaktan bir proje derlemek istediğinizde size lazım olacak.
Bu rehberde Linux üzerinde Go'yu resmi tarball ile kurmayı, PATH değişkenini kalıcı olarak ayarlamayı, go version ile kurulumu doğrulamayı, GOPATH ile modern modül sisteminin farkını, go build ve go run komutlarını ve derlenmiş tek dosyalık binary'nin neden bu kadar pratik olduğunu adım adım anlatacağım. Sonunda bu binary'yi systemd altında bir servis olarak çalıştırmaya da köprü kuracağız; böylece yazdığınız program sunucu her açıldığında kendiliğinden ayağa kalksın. Anlatım boyunca dağıtımdan bağımsız, kıdemli bir yöneticinin müşterisine gösterdiği gibi net komutlarla ilerleyeceğim.
Neden Paket Yöneticisi Yerine Resmi Tarball?#
Ubuntu'da apt install golang, CentOS/Rocky tarafında dnf install golang komutları elbette çalışır. Ama dağıtımların depolarındaki Go sürümü çoğu zaman aylar, bazen bir yıl geriden gelir. Go ekibi her altı ayda bir yeni bir ana sürüm yayımlıyor ve dil aktif geliştirildiği için güncel sürümle çalışmak modül uyumu ve güvenlik yamaları açısından önemli. Bir projeyi kaynaktan derlerken go.mod dosyasında go 1.22 yazıyorsa ve sizin sisteminizde depodan gelen 1.18 varsa derleme baştan patlar.
Resmi tarball yöntemi ise her zaman en güncel sürümü verir, tek bir dizine kurulur (/usr/local/go), sistem paketlerine hiç dokunmaz ve sürümü yükseltmek istediğinizde eski dizini silip yenisini açmak yeterlidir. Bu izole yapı, aynı sunucuda birden çok projeyi farklı gereksinimlerle çalıştırdığınızda kafa karışıklığını da azaltır. Aşağıdaki adımların tamamı bu resmi yöntem üzerine kurulu. Sunucunuza SSH erişiminiz olduğunu ve sudo yetkiniz bulunduğunu varsayıyorum; henüz kendi sunucunuz yoksa bir VDS sunucu üzerinde bu adımların hepsini rahatça uygulayabilirsiniz.
Doğru Sürümü ve Mimariyi İndirmek#
Önce sunucunuzun mimarisini öğrenin, çünkü indireceğiniz tarball buna göre değişir. Çoğu bulut sunucu x86_64 (Go dünyasında amd64), ARM tabanlı örnekler ise aarch64 (arm64) mimarisindedir.
uname -m
# x86_64 -> amd64 paketi
# aarch64 -> arm64 paketi
Ardından resmi indirme adresinden güncel sürümü wget veya curl ile çekin. Aşağıdaki komutta sürüm numarasını (1.22.5) örnek olarak yazdım; siz go.dev/dl sayfasındaki en güncel kararlı sürümü kullanın.
cd /tmp
wget https://go.dev/dl/go1.22.5.linux-amd64.tar.gz
İndirdikten sonra dosyanın bütünlüğünü doğrulamak iyi bir alışkanlıktır. İndirme sayfasında her paketin yanında bir SHA256 özeti bulunur; kendi indirdiğiniz dosyanın özetini alıp karşılaştırın.
sha256sum go1.22.5.linux-amd64.tar.gz
# çıkan uzun hex değerini go.dev/dl sayfasındaki değerle karşılaştırın
İki değer birebir aynıysa dosya bozulmamış ve araya girilmemiş demektir. Bu adımı geçmek cazip gelse de, indirdiğiniz ikili dosyayı sistemin ayrıcalıklı bir dizinine açacağınız için doğrulama alışkanlığı güvenlik açısından değerlidir.
Tarball'ı /usr/local/go Altına Açmak#
Go'yu kurmanın resmi ve önerilen yolu, arşivi /usr/local altına açmaktır; bu işlem /usr/local/go dizinini oluşturur. Yeni bir sürüme geçerken tuhaf karışımlar yaşamamak için önce varsa eski kurulumu temizleyin, sonra arşivi açın.
# Varsa eski kurulumu kaldır (yükseltme senaryosu)
sudo rm -rf /usr/local/go
# Arşivi /usr/local altına aç
sudo tar -C /usr/local -xzf /tmp/go1.22.5.linux-amd64.tar.gz
-C /usr/local bayrağı, tar'a "arşivi bu dizine aç" der. İşlem bittiğinde /usr/local/go/bin altında go ve gofmt çalıştırılabilir dosyalarını göreceksiniz. Dizin yapısına hızlıca göz atalım:
ls /usr/local/go
# api bin doc lib misc pkg src test VERSION
Burada bin klasörü derleyiciyi barındırır, src standart kütüphanenin kaynak kodunu içerir, VERSION dosyası ise kurulu sürümü tutar. Kurulumun kendisi bu kadar; dosyalar yerinde. Ancak şu an go komutunu doğrudan çalıştıramazsınız çünkü kabuğunuz /usr/local/go/bin dizinini henüz tanımıyor. Sıradaki adım tam olarak bunu çözüyor.
PATH Değişkenini Kalıcı Olarak Ayarlamak#
go komutunu her dizinden çalıştırabilmek için /usr/local/go/bin yolunu PATH ortam değişkenine eklemeniz gerekir. Terminalde tek seferlik export PATH=$PATH:/usr/local/go/bin yazmak o oturum için çalışır ama SSH bağlantısını kapattığınızda kaybolur. Kalıcı olması için kabuğunuzun başlangıç dosyasına yazmalısınız.
Tek bir kullanıcı için ayarlıyorsanız ~/.bashrc (veya zsh kullanıyorsanız ~/.zshrc) dosyasının sonuna ekleyin:
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
Sunucuda birden fazla kullanıcı Go kullanacaksa, ayarı sistem geneli yapmak daha temizdir. /etc/profile.d/ altına küçük bir betik koymak en düzenli yöntemdir:
echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee /etc/profile.d/go.sh
sudo chmod +x /etc/profile.d/go.sh
Bu dosya sistemdeki her kullanıcı oturum açtığında otomatik yüklenir. source ~/.bashrc çalıştırdıktan veya oturumu yeniden açtıktan sonra go komutu artık her yerden erişilebilir olacak. İki ortamı karşılaştıralım:
| Yöntem | Kapsam | Kalıcılık | Ne zaman |
|---|---|---|---|
export (terminalde) | Sadece o oturum | Hayır | Hızlı test |
~/.bashrc | Tek kullanıcı | Evet | Kişisel sunucu |
/etc/profile.d/go.sh | Tüm kullanıcılar | Evet | Ekip / paylaşımlı sunucu |
go version ile Kurulumu Doğrulamak#
Kurulumun düzgün olduğunu görmenin en hızlı yolu sürümü sorgulamaktır. Yeni bir terminal açın veya başlangıç dosyasını source ile yeniden yükleyin, ardından şunu çalıştırın:
go version
# go version go1.22.5 linux/amd64
Bu çıktıyı aldıysanız derleyici çalışıyor demektir. Bir adım öteye gidip Go'nun ortam ayarlarını da görebilirsiniz; bu, ileride sorun giderirken çok işinize yarar:
go env GOROOT GOPATH GOOS GOARCH
# /usr/local/go
# /home/kullanici/go
# linux
# amd64
Burada GOROOT, Go'nun kendisinin kurulu olduğu yeri (/usr/local/go) gösterir ve normalde ona elle dokunmanıza gerek yoktur. GOPATH ise sizin çalışma alanınızı işaret eder; varsayılan olarak ev dizininizde go klasörüdür. Eğer go version "command not found" derse PATH ayarınız yüklenmemiştir; terminali kapatıp yeniden açın veya echo $PATH ile /usr/local/go/bin yolunun listede olup olmadığını kontrol edin.
GOPATH ve Modül Sistemi: Eski ve Yeni Dünya#
Go'nun ilk yıllarında tüm proje kodları tek bir merkezi dizin olan GOPATH altında, src/github.com/kullanici/proje gibi katı bir hiyerarşide tutulmak zorundaydı. Bu yapı öğrenmesi zor ve bağımlılık sürümlerini kilitlemekte yetersizdi. Go 1.11 ile gelen modül sistemi (Go Modules) bu zorunluluğu ortadan kaldırdı. Artık projenizi diskte istediğiniz herhangi bir dizinde tutabilir, bağımlılıklarını go.mod adında bir dosyada sürümleriyle birlikte sabitleyebilirsiniz. Bu, tıpkı Node.js'teki package.json gibi düşünülebilir.
Bugün GOPATH'i genelde sadece iki iş için tanırsınız: indirilen modüllerin önbelleği ($GOPATH/pkg/mod) ve go install ile kurduğunuz komut satırı araçlarının konduğu yer ($GOPATH/bin). Bu son klasörü de PATH'e eklerseniz go install ile kurduğunuz araçları doğrudan çağırabilirsiniz:
echo 'export PATH=$PATH:$(go env GOPATH)/bin' >> ~/.bashrc
source ~/.bashrc
Yeni bir proje başlatmak artık son derece basit. Boş bir dizin açın ve içinde go mod init çalıştırın; bu komut projenizin modül yolunu belirleyen go.mod dosyasını üretir.
mkdir ~/merhaba && cd ~/merhaba
go mod init ornek.com/merhaba
# go: creating new go.mod: module ornek.com/merhaba
Modül yolu (ornek.com/merhaba) genellikle kodunuzu barındıracağınız depo adresidir. Bu yüzden gerçek projelerde github.com/kullaniciadi/proje biçiminde yazılır. Sürüm kontrolüyle henüz tanışmadıysanız Git'in temelleri rehberi, go.mod'un neden bir depo adresine bağlı olduğunu anlamanıza yardımcı olur.
İlk Programı Yazmak, go run ve go build#
Şimdi klasik ilk programı yazalım. ~/merhaba dizininde main.go adında bir dosya oluşturun ve şu içeriği koyun:
package main
import "fmt"
func main() {
fmt.Println("Merhaba, Clou.TR sunucusundan selamlar!")
}
Bu programı iki farklı şekilde çalıştırabilirsiniz. Geliştirme sırasında hızlı denemeler için go run idealdir; kodu derler, bellekte çalıştırır ve geride bir dosya bırakmaz:
go run main.go
# Merhaba, Clou.TR sunucusundan selamlar!
Programınızı üretimde çalıştıracak, başka bir sunucuya taşıyacak veya bir servise dönüştürecekseniz go build kullanmalısınız. Bu komut, çalıştırılabilir tek bir dosya üretir:
go build -o merhaba
ls -lh merhaba
# -rwxr-xr-x 1 kullanici kullanici 1.8M ... merhaba
./merhaba
# Merhaba, Clou.TR sunucusundan selamlar!
İki komut arasındaki farkı akılda tutmak için şu tablo yeterli:
| Komut | Ne yapar | Çıktı dosyası | Kullanım yeri |
|---|---|---|---|
go run | Derler ve çalıştırır | Yok (geçici) | Geliştirme, hızlı test |
go build | Derler, dosya bırakır | Var (binary) | Üretim, dağıtım |
go install | Derler, $GOPATH/bin'e koyar | Var (araç) | Komut satırı araçları |
Kodunuzu düzenli tutmak için gofmt (veya go fmt ./...) komutunu da alışkanlık edinin; Go'nun resmi biçimlendiricisi tüm ekibin aynı stilde kod yazmasını sağlar.
Tek Dosyalık Binary'nin Gücü ve Çapraz Derleme#
Go'nun sunucu tarafında bu kadar sevilmesinin asıl nedeni burada. go build'in ürettiği dosya statik olarak bağlanmıştır; yani çalışması için sistemde ayrı bir yorumlayıcıya (Python gibi) veya bir yığın paylaşımlı kütüphaneye (.so dosyaları) ihtiyaç duymaz. Bir Python uygulamasını taşırken sanal ortam, pip bağımlılıkları ve doğru sürüm derdiyle uğraşırsınız; Go'da ise scp merhaba sunucu:/opt/ yeterlidir. Kopyaladığınız dosya, hedef makinede aynı işletim sistemi ve mimari olduğu sürece çalışır.
Dahası, Go tek bir makineden farklı platformlar için derleme yapabilir. GOOS ve GOARCH değişkenlerini ayarlayarak, amd64 bir sunucuda oturup ARM tabanlı bir cihaz için binary üretebilirsiniz:
# amd64 Linux için
GOOS=linux GOARCH=amd64 go build -o merhaba-amd64
# ARM64 Linux için (örn. bazı bulut örnekleri, Raspberry Pi)
GOOS=linux GOARCH=arm64 go build -o merhaba-arm64
# Boyutu küçültmek için hata ayıklama sembollerini at
go build -ldflags="-s -w" -o merhaba-kucuk
-ldflags="-s -w" bayrağı, hata ayıklama bilgilerini çıkararak binary boyutunu belirgin şekilde küçültür; sadece üretime çıkacak sürümlerde kullanmanızı öneririm. Bu taşınabilirlik özelliği, uygulamalarınızı Docker imajlarına koyarken de son derece işinize yarar: scratch gibi neredeyse boş bir temel imajın üzerine tek bir Go binary'si koyarak birkaç megabaytlık, saldırı yüzeyi minimal konteynerler üretebilirsiniz.
Derlenen Binary'yi systemd ile Servise Dönüştürmek#
Yazdığınız program bir web sunucusu, bir API veya bir arka plan işçisiyse, onu terminalde elle başlatmak yerine bir sistem servisi olarak çalıştırmak istersiniz. Böylece sunucu yeniden başladığında program da otomatik ayağa kalkar ve çökerse systemd onu tekrar başlatır. Önce binary'yi kalıcı bir konuma koyalım:
sudo cp merhaba /usr/local/bin/merhaba
sudo useradd -r -s /usr/sbin/nologin merhaba || true
Burada uygulamaya özel, oturum açamayan bir sistem kullanıcısı oluşturduk; servisi root yerine bu kısıtlı kullanıcıyla çalıştırmak güvenlik açısından önemli. Şimdi /etc/systemd/system/merhaba.service dosyasını oluşturun:
[Unit]
Description=Merhaba Go Uygulamasi
After=network.target
[Service]
Type=simple
User=merhaba
ExecStart=/usr/local/bin/merhaba
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Servisi devreye almak için systemd'yi yeniden yükleyip başlatın ve açılışta otomatik başlaması için etkinleştirin:
sudo systemctl daemon-reload
sudo systemctl enable --now merhaba.service
sudo systemctl status merhaba.service
Artık uygulamanız bir sistem servisi. Loglarını journalctl -u merhaba -f ile canlı izleyebilir, kodda değişiklik yaptığınızda yeniden derleyip sudo systemctl restart merhaba ile güncelleyebilirsiniz. Bir web uygulaması yazdıysanız, önüne ters vekil (reverse proxy) olarak Nginx koyup TLS'i orada sonlandırmak yaygın bir yaklaşımdır; bu noktada bir SSL sertifikası ile trafiği şifrelemeyi ve gelen istekleri WAF koruması ile filtrelemeyi ihmal etmeyin. Kaynak kontrolü, güncelleme yönetimi ve yedekleme gibi işleri kendiniz üstlenmek istemiyorsanız sunucu yönetimi hizmetimiz bu operasyonel yükü sizin adınıza taşır.
Sıkça Sorulan Sorular#
Go'yu apt veya dnf ile mi yoksa tarball ile mi kurmalıyım?#
Öğrenme ve deneme amaçlı hızlı bir kurulum için paket yöneticisi yeterlidir, ancak güncel sürümle çalışmak, modül uyumunu korumak ve sürüm yükseltmeyi kolaylaştırmak istiyorsanız resmi tarball yöntemini öneririm. Depolardaki sürümler çoğu zaman geridedir ve bir projeyi go.mod'daki minimum sürüm gereksinimiyle derlerken sizi zorlayabilir. Tarball kurulumu tek dizine yerleştiği için sistemi de kirletmez.
go version komutu "command not found" hatası veriyor, ne yapmalıyım?#
Bu neredeyse her zaman PATH ayarının yüklenmemiş olmasından kaynaklanır. Başlangıç dosyanıza (~/.bashrc veya /etc/profile.d/go.sh) /usr/local/go/bin satırını eklediğinizden emin olun, ardından terminali kapatıp yeniden açın veya source ~/.bashrc çalıştırın. echo $PATH çıktısında /usr/local/go/bin görünmüyorsa ayar aktif değildir. Ayrıca ls /usr/local/go/bin/go ile dosyanın gerçekten orada olduğunu doğrulayın.
GOPATH'i mutlaka ayarlamam gerekiyor mu?#
Hayır, modern Go'da elle GOPATH ayarlamanıza gerek yok. Varsayılan değeri ev dizininizdeki go klasörüdür ve modül sistemi sayesinde projelerinizi diskte istediğiniz yerde tutabilirsiniz. GOPATH'i yalnızca go install ile kurduğunuz araçların bin klasörünü PATH'e eklemek için tanımanız faydalı olur; onun dışında çoğu geliştirici ona hiç dokunmaz.
go run ile go build arasındaki fark nedir?#
go run kodunuzu derleyip anında çalıştırır ve geride kalıcı bir dosya bırakmaz; geliştirme sırasında hızlı denemeler için idealdir. go build ise çalıştırılabilir tek bir dosya (binary) üretir ve bu dosyayı başka sunuculara taşıyabilir, servis olarak çalıştırabilirsiniz. Kısaca go run denemek, go build dağıtmak içindir.
Bir sunucuda derleyip başka bir sunucuda çalıştırabilir miyim?#
Evet, Go'nun en güçlü yanlarından biri budur. go build statik olarak bağlanmış bir dosya ürettiği için, hedef sunucuda aynı işletim sistemi ve mimari olduğu sürece dosyayı scp ile kopyalamanız yeterlidir; ayrıca bir yorumlayıcı veya kütüphane kurmanız gerekmez. Farklı bir mimari için derlemeniz gerekiyorsa GOOS ve GOARCH değişkenlerini ayarlayarak çapraz derleme yapabilirsiniz.
Go binary'sinin boyutu neden birkaç megabayt?#
Çünkü Go, çalışma zamanını (garbage collector, zamanlayıcı vb.) ve kullandığınız tüm kütüphaneleri doğrudan dosyanın içine gömer; hiçbir harici bağımlılığa ihtiyaç bırakmaz. Bu, taşınabilirlik uğruna ödenen küçük bir bedeldir. Üretime çıkarken -ldflags="-s -w" bayrağıyla hata ayıklama sembollerini atarak boyutu belirgin ölçüde düşürebilir, dilerseniz upx gibi araçlarla daha da sıkıştırabilirsiniz.
Kapanış#
Bu rehberde Go'yu resmi tarball ile /usr/local/go altına kurmayı, PATH'i kalıcı ayarlamayı, go version ile doğrulamayı, modül sisteminin GOPATH'e göre farkını, go run ve go build ile ilk programı çalıştırmayı ve derlenen binary'yi systemd ile bir servise dönüştürmeyi baştan sona ele aldık. Tek dosyalık, bağımlılıksız binary üretme yeteneği Go'yu sunucu tarafı araçlar ve mikroservisler için ideal kılıyor; öğrendikçe kendi izleme betiklerinizden tam kapsamlı API'lere kadar pek çok şeyi rahatça yazabileceksiniz.
Uygulamalarınızı çalıştıracak sağlam bir altyapıya ihtiyacınız varsa, tam kök erişimi sunan VDS ve sanal sunucu paketlerimizle Go binary'lerinizi dakikalar içinde ayağa kaldırabilir, sunucu yönetimi hizmetimizle güncelleme ve yedekleme yükünü bize bırakabilirsiniz. Daha kapsamlı bir kurulum planlıyorsanız tüm sunucu çözümlerimize göz atın; ekibimiz doğru mimariyi seçmenizde size yardımcı olmaktan memnuniyet duyar.