---
title: 'Ortam Kurulumu ve İlk Program'
source: 'https://academia.sh/tr/kurslar/go-temelleri/ortam-kurulumu-ve-ilk-program'
course: 'Go Temelleri'
language: tr
updated: '2026-08-23T14:25:00+00:00'
license: 'CC BY-SA 4.0'
---

# Ortam Kurulumu ve İlk Program

Bir Go kaynağının derlenebilmesi için üç şey zorunludur: paket bildirimi, giriş noktası (func main) ve modül dosyası; üçünden biri eksik olduğunda, kaynağın geri kalanı hiç değişmese bile derleme reddediliyor — modül dosyası kaynağın kendisinde hiç durmuyor.

Önceki ders dört ret nedenini ölçtü; hepsi kaynağa **fazladan** bir şey yazıldığında ya da bir
sözün tutulmadığında ortaya çıkıyordu. Bu ders tersini soruyor: bir kaynağın hiç derlenip
çalışabilmesi için yazılması **zorunlu** olan en küçük küme nedir? Bir Go programı üç şeyi
birden ister — bir paket bildirimi, bir giriş noktası, bir modül dosyası — ve bunlardan biri
eksik olduğunda kaynağın geri kalanı ne kadar doğru yazılmış olursa olsun derleme durur.

Bilgisayarlar Nasıl Çalışır kursu (M01/K01) bir programın işletim sistemi tarafından nasıl
başlatıldığını, giriş noktası kavramını ve bir sürecin ilk komuta nasıl ulaştığını kavram
olarak kurdu. **Bu burada tekrar kurulmaz** — farkı tek cümleyle yazmak yeter: orada giriş
noktasının **var olması gerektiği** anlatıldı, burada Go'nun bu gerekliliği **hangi imzayla**
ve **derleme zamanında** denetlediği ölçülüyor.

## Üç Zorunlu Parça

Üçü de farklı bir yerde durur. Paket bildirimi (`package main`) kaynağın **ilk satırıdır** ve
hangi paketin parçası olduğunu söyler; çalıştırılabilir bir program için bu paket adı `main`
olmak zorundadır. Giriş noktası, `main` paketi içinde tanımlanan `func main()` işlevidir ve
sanal makinenin değil, doğrudan işletim sisteminin çağıracağı ilk Go koludur. Modül dosyası ise
kaynağın **dışındadır** — kaynakla aynı dizinde duran ayrı bir metin dosyası, `go.mod`, ve
derleyiciye "bu dizin bir modülün köküdür" diyen tek şey odur.

Üçünün de zorunlu olması bir tesadüf değil, üç ayrı sorunun yanıtı. Paket bildirimi "bu kaynak
neyin parçası" sorusuna yanıt verir ve tek bir kaynak dosyasının bile paketsiz duramayacağını
söyler — Go'da paketsiz bir kaynak diye bir şey yoktur, en küçük program bile bir paket adı
taşımak zorundadır. Giriş noktası "çalıştırma buradan mı başlıyor" sorusuna yanıt verir; bir
paket, birden fazla işlev barındırabilir ama işletim sistemine hangi işlevden başlanacağını
söyleyen tek bir imza vardır. Modül dosyası ise "bu paket nerede duruyor" sorusuna yanıt verir
ve paketin kendisinden bağımsız bir bilgi taşır — aynı paket adı birçok farklı dizinde tekrar
edebilir, ama bir dizinin hangi modüle ait olduğu yalnız o dizindeki (ya da üstündeki) `go.mod`
dosyasından okunur.

Üç sorunun üçü de "zorunlu" göründüğü için, bunları ayrı ayrı doğrulamak yerine tek bir kontrol
listesi gibi ele almak cazip gelebilir — "üçü de eksiksiz mi" diye tek bir denetim. Bu ders
tam tersini yapıyor: her birini **teker teker** kaldırıp sonucu ayrı ayrı okuyor, çünkü aynı
`derlenmedi` yanıtının arkasında üç ayrı neden durabiliyor ve bu üç nedenin hangi aşamada
ortaya çıktığını bilmek, bir kaynağın neden derlenmediğini anlamanın ilk adımı.

Bu üç parçayı tek tek kaldırıp derlenme sonucunu ölçeceğiz. Ölçüm aracı, önceki dersin
`derlenirMi` işlevine çok yakın; tek farkı, modül dosyasının yazılıp yazılmayacağını ayrıca bir
parametre olarak almasıdır.

```go
// derleme.go — parcalari denetleyerek derleyen yardimci
package main

import (
	"os"
	"os/exec"
	"path/filepath"
)

func derlenirMiParcalar(kaynak string, modYaz bool) bool {
	dizin, err := os.MkdirTemp("", "sinama")
	if err != nil {
		return false
	}
	defer os.RemoveAll(dizin)
	if modYaz {
		os.WriteFile(filepath.Join(dizin, "go.mod"), []byte("module sinama\n\ngo 1.24\n"), 0o644)
	}
	os.WriteFile(filepath.Join(dizin, "kod.go"), []byte(kaynak), 0o644)
	cmd := exec.Command("go", "build", "./...")
	cmd.Dir = dizin
	cmd.Env = append(os.Environ(), "GOTOOLCHAIN=local")
	return cmd.Run() == nil
}

func sinif(ok bool) string {
	if ok {
		return "derlendi"
	}
	return "derlenmedi"
}
```

**DT4.** Ölçüm aracı bir önceki dersten tek bir parametre uzağa açılıyor: `modYaz`, modül
dosyasının o koşumda yazılıp yazılmayacağını belirler. Kaynağın kendisi bu parametreden hiç
etkilenmez; bu, aşağıdaki dördüncü satırın neyi ölçtüğünü doğru okumak için gerekli.

Bu genişleme küçük görünse de bir tasarım kararı taşıyor: önceki derste yazılmamışlığın yeri
her zaman kaynağın **içindeydi** — bir satır ya vardı ya yoktu. Bu derste yazılmamışlığın yeri
ilk kez kaynağın **dışına** taşınıyor ve ölçüm aracının bunu ayrı bir bağımsız değişkenle
temsil etmesi gerekiyor. Bir sonraki bölümde bu ayrımın neden önemli olduğu görülecek.

Dört durumu sırayla koşturuyoruz: hiçbir parça eksik değilken, paket bildirimi yokken, giriş
noktası yokken, modül dosyası yokken.

```go
// parcalar.go — uc zorunlu parcanin her biri tek tek kaldirilir
package main

import "fmt"

const tamKaynak = `package main

func main() {}
`
const paketsizKaynak = `func main() {}
`
const anasizKaynak = `package main
`

func main() {
	fmt.Printf("%-30s %s\n", "eksik parca", "sonuc")
	fmt.Printf("%-30s %s\n", "hicbiri eksik degil", sinif(derlenirMiParcalar(tamKaynak, true)))
	fmt.Printf("%-30s %s\n", "paket bildirimi yok", sinif(derlenirMiParcalar(paketsizKaynak, true)))
	fmt.Printf("%-30s %s\n", "giris noktasi (main) yok", sinif(derlenirMiParcalar(anasizKaynak, true)))
	fmt.Printf("%-30s %s\n", "modul dosyasi yok", sinif(derlenirMiParcalar(tamKaynak, false)))
}
```

```
eksik parca                    sonuc
hicbiri eksik degil            derlendi
paket bildirimi yok            derlenmedi
giris noktasi (main) yok       derlenmedi
modul dosyasi yok              derlenmedi
```

İlk satır kontrol grubudur: hiçbir parça eksik değilken kaynak derlenir. Sonraki üç satırın her
biri, kontrol grubundan tek bir parçayı çıkarır ve sonuç aynı yönde değişir — üçü de derlemeyi
durdurur. Ama üçü aynı **nedenden** durdurmaz. Paket bildirimi yokken derleyici kaynağın hangi
pakete ait olduğunu hiç bilmiyor; bu, en erken kesilen daldır, çünkü paket adı kaynağın ilk
satırında beklenir. Giriş noktası yokken kaynak geçerli bir paket olarak **derlenir** ama
yürütülebilir bir dosya üretilmez — kaynakta hata yoktur, yalnız çalıştırılabilir bir uçtan
yoksundur; `go build ./...` bunu da derlenmedi sayıyor, çünkü `main` paketi için giriş noktası
zorunlu bir sözleşmedir. Dördüncü satır ise en dolaylı olanı ve dersin sınırlayıcı ölçümüne
taşıyor.

`paketsizKaynak` sabitine bakılırsa, eksik olan tek şey bir satırdır: `package main`. Bu satır
kaldırıldığında geriye kalan `func main() {}` başlı başına anlamsız değildir — bir işlev
tanımıdır ve sözdizimi doğrudur. Derleyicinin reddi burada sözdizimine değil, **bağlama**
yöneliktir: her Go dosyası bir paketin parçası olarak okunur ve paket adı olmadan bir dosyayı
hiçbir pakete yerleştiremez. Bu, önceki dersteki dört retten farklı bir tondadır: oradaki
dört kaynak sözdizimi kurallarını çiğniyordu, buradaki kaynak sözdizimi açısından eksiksiz bir
işlev gövdesidir ama **kimliksizdir**.

İlk iki ret, önceki dersin ölçtüğü dört rete yakın bir aileden: ikisi de kaynağın kendi
sözdiziminde eksik bırakılan bir şeydir ve derleyici bunu kaynağı **okurken** görür. Giriş
noktasının yokluğu farklı bir aşamada yakalanıyor. `go build` iki işi art arda yapar: önce
kaynağı bir pakete derler, sonra o paketten çalıştırılabilir bir dosya **bağlar**. Paket
derlemesi `main.go`yu geçerli bir Go dosyası olarak kabul eder; bağlama aşaması, `main`
paketinin bir `func main()` işlevi taşımasını arar ve bulamayınca durur. Bu ayrım önemlidir,
çünkü aynı kaynak farklı bir bağlamda —örneğin başka bir programın içe aktardığı bir kitaplık
paketi olarak— hiçbir sorun çıkarmadan derlenebilirdi; giriş noktası zorunluluğu yalnız `main`
paketine, yalnız çalıştırılabilir bir dosya istendiğinde uygulanıyor.

## İki Dosya, Tek Paket

Üç zorunlu parça, tek bir dosyada mı durmak zorunda? Değil. Aynı dizindeki iki dosya, aynı
paket bildirimini taşıdığı sürece **tek pakete** ait sayılır ve birlikte derlenir — biri
`func main` taşımasa bile. Yukarıdaki `derleme.go` ile bu derste kullanılan diğer bütün
dosyalar zaten bunu gösteriyordu; burada aynı deseni en yalın hâliyle kuruyoruz.

Bunun pratik önemi, bir programın büyümesiyle ortaya çıkıyor. `func main()` içeren tek bir
dosyaya her şeyi yazmak zorunda olsaydık, bir programın uzunluğu tek dosyanın okunabilirliğiyle
sınırlı kalırdı. Go, bir paketi dosya sayısına göre değil, paket bildirimine göre tanımladığı
için, aynı paketin sorumluluklarını birden fazla dosyaya dağıtmak mümkün — üstelik bu bölünme
derleme sonucunu hiç değiştirmiyor: `derleme.go`, `yardim.go` ve `birlikte.go` üç ayrı dosya
olarak da tek bir dosyaya birleştirilmiş gibi de derlenirdi, aynı ikili dosyayı üretirdi.
Bölünme kararı, tamamen okuyan ve yazan tarafın rahatlığı için var.

```go
// yardim.go — ikinci dosya, ayni pakete ait
package main

import "fmt"

func selamla(ad string) string {
	return fmt.Sprintf("merhaba, %s", ad)
}
```

```go
// birlikte.go — iki ayri dosya, tek paket, birlikte derlenir
package main

import "fmt"

func main() {
	fmt.Println(selamla("paket"))
}
```

```
merhaba, paket
```

**DT5.** `birlikte.go`, `yardim.go`'da tanımlanan `selamla` işlevini hiçbir içe aktarım
yazmadan çağırıyor. Bu derste ölçülen şey ikinci bir dosyanın varlığı değil — onu bu derse
kadar zaten kullanıyorduk — iki ayrı dosyanın **tek bir ikili dosyaya** derlendiğidir: `go run
.` dizindeki bütün `.go` dosyalarını okur, aralarında içe aktarım aramaz, yalnız paket adının
eşleştiğini denetler.

Bu davranış, önceki ölçümdeki "hiçbiri eksik değil" satırını da baştan okumamızı gerektiriyor.
O satırda kullanılan tek dosyalık `tamKaynak`, `derleme.go`nun **dışında**, kendi başına bir
pakete yazılıp derlenmişti — orada `sinif` ve `derlenirMiParcalar` çağrılmıyordu, kaynak yalnız
`package main` ve boş bir `func main` taşıyordu. Burada ise `birlikte.go`, aynı dizindeki
`yardim.go`ya bağımlı ve o bağımlılık dosya sınırını hiç aşan bir içe aktarım gerektirmiyor.
İki ölçüm birbirini tamamlıyor: biri paketin en küçük hâlini, öbürü paketin birden fazla
dosyaya yayılmış hâlini gösteriyor.

Bu, paket bildiriminin neden dosya başına yazıldığını da açıklıyor: derleyici, hangi
dosyaların birlikte bir bütün oluşturduğunu **dosya adından değil**, her dosyanın kendi ilk
satırından öğreniyor. `derleme.go`, `yardim.go` ve `birlikte.go` üçü de `main` yazıyor ve
üçü de aynı pakete katılıyor; herhangi biri farklı bir ad yazsaydı derleme aynı dizinde bile
dururdu.

Bu davranışın bir sonucu, içe aktarımların **iki farklı düzeyde** çalıştığıdır. `birlikte.go`,
`fmt` paketini kendi başına içe aktarıyor, çünkü standart kitaplığın bir parçasını kullanıyor;
ama `yardim.go`da tanımlanan `selamla`yı içe aktarmıyor, çünkü o zaten aynı paketin bir
parçası. İçe aktarım satırı yalnız **paket sınırını** geçen adlar için gerekiyor — aynı paketin
içinde, dosya sınırı bir anlam taşımıyor. Kursun paketler konusu bu sınırı tersine çevirecek:
orada dosyalar aynı pakette kalmaya devam edecek, ama bazı adlar paketin **dışından** hiç
görünmeyecek.

## Sınırlayıcı Ölçüm: Modül Dosyası Kaynağın İçinde Değildir

Dördüncü satıra dönelim. `modul dosyasi yok` satırında kullanılan kaynak, ilk satırdakiyle
**bayt bayt aynıdır** — `tamKaynak` sabiti iki çağrıda da değişmeden geçiyor. Aradaki tek fark,
`derlenirMiParcalar`'a verilen `modYaz` bağımsız değişkeninin `false` olmasıdır: geçici dizine
`go.mod` hiç yazılmıyor.

**DT6.** Bu satırda ölçülen şey bir kaynak hatası değil, bir **bağlam eksikliğidir**. Kaynağın
kendisinde paket bildirimi de giriş noktası da eksiksiz duruyor; derleyici yine de reddediyor,
çünkü hangi modülün parçası olduğunu bilmeden bir dizini derlemeyi kabul etmiyor.

Bu satır, dersin ilk iki reddinden kalitatif olarak ayrılıyor. Paket bildirimini ya da giriş
noktasını kaldırırken kaynağa **dokunuyorduk**; burada kaynak hiç açılmadı bile, yalnız
dizindeki başka bir dosya silindi. Bir okuyucu, `tamKaynak` sabitine baksa, onun neden bazen
derlendiğini bazen derlenmediğini kaynağın kendisinden çıkaramaz — cevap kaynağın dışında,
dizinin içeriğinde duruyor.

Bunun pratik sonucu şu: bir kaynak dosyasını başka bir dizine kopyalamak, o dizinde bir modül
dosyası yoksa hiçbir işe yaramaz — kaynak aynen kopyalanmış olsa bile derlenmez. Modül dosyası,
paket bildirimi gibi kaynağın **parçası** değildir; kaynağın **bağlamıdır**. Bu ayrım önemlidir
çünkü ikisi de "zorunlu" sayıldığı hâlde farklı bir şeye zorunludur: paket bildirimi kaynağın
kendi kimliğini taşır, modül dosyası kaynağın **nerede** durduğunu bildirir. Kursun paketler
konusu bu ayrımı derinleştirecek; burada ölçülen yalnız zorunluluğun kendisidir — modül dosyası
olmadan hiçbir kaynak, ne kadar doğru yazılırsa yazılsın, bir ikili dosyaya dönüşmez.

Bu derste kullanılan ölçüm aracı, modül dosyasının **içeriğini** hiç değiştirmedi — yalnız var
olup olmadığını değiştirdi. Bir modül dosyası, kendi başına, dışarıdan hiçbir bağımlılık
istemeyen en küçük hâliyle bile zorunludur; içine hiçbir bağımlılık satırı eklenmemiş olması,
derleyicinin modülü reddetmesi için bir neden değildir. Zorunlu olan modül dosyasının **var
olması**, içeriğinin ne kadar dolu olduğu değil.

Modül dosyasının kaynaktan bağımsız olması, aynı kaynağın **birden fazla** modülün altına
taşınabileceği anlamına da geliyor: dizini değiştirip yeni bir `go.mod` yazmak, kaynağı hiç
değiştirmeden onu başka bir modülün parçası yapar. Paket bildirimini değiştirmek ise kaynağın
kendisini değiştirmek demektir. İkisi arasındaki bu fark, "zorunlu" sözcüğünün tek bir anlama
gelmediğini gösteriyor — bir şey kaynağın **içinde** zorunlu olabilir, bir şey kaynağın
**etrafında** zorunlu olabilir, ve ikisinin kaldırılma bedeli aynı değildir: biri kaynağı
bozar, öbürü yalnız kaynağın bulunduğu yeri geçersiz kılar.

Bu üçlü ayrım — kimlik, sözleşme, bağlam — ilk derste ölçülen dört rede de geriye dönük bir
çerçeve veriyor. Kullanılmayan değişken ve kullanılmayan içe aktarım, kaynağın kendi kimliğiyle
ilgiliydi: kaynakta yazılan her ad, kaynağın bir parçası olarak kalmayı hak etmeli. Yazılmayan
dönüş değeri bir sözleşme ihlaliydi: imza bir söz verir, gövde onu tutmalı. Bu derste eklenen
üçüncü kategori — bağlam — ilk derste hiç görünmedi, çünkü o dersteki dört kaynak zaten bir
modülün içine yazılıyordu. Zorunluluğun üç ayrı yerde durabileceğini görmek, kursun ilerleyen
derslerinde tekrar işe yarayacak: bir değişkenin sıfır değeri onun **kimliğine**, bir işlevin
adlandırılmış dönüşü onun **sözleşmesine**, bir paketin dışa aktarma kuralı ise onun
**bağlamına** ait olacak. Bu üç kategori bu kursta hiçbir yerde adıyla anılmayacak — burada
kurulan yalnız bir okuma alışkanlığı: bir `derlenmedi` yanıtı görüldüğünde ilk soru "hangi
satır eksik" değil, "eksik olan şey kaynağın neresinde duruyor" olmalı.

## Özet

- Bir Go kaynağının derlenebilmesi için üç şey zorunludur: paket bildirimi, giriş noktası
  (`func main`), modül dosyası.
- Üçü de eksikken derleme durur, ama üçü aynı nedenden durmaz: biri kaynağın kimliğini, biri
  sözleşmesini, biri bağlamını eksik bırakır.
- Aynı dizindeki iki dosya, aynı paket adını taşıdığı sürece içe aktarım yazmadan birbirini
  görür ve tek bir ikili dosyaya derlenir.
- Modül dosyası kaynağın parçası değil bağlamıdır: aynı kaynak, hiç değişmeden, modül dosyası
  kaldırıldığında derlenmez hâle gelir.
- Zorunluluk tek bir anlama gelmiyor — kaynağın içinde zorunlu olanla kaynağın etrafında
  zorunlu olan, kaldırıldığında farklı bir bedel ödetiyor.

## Sonraki Adım

Bu derste bir kaynağın **çalışabilmesi** için gerekenler ölçüldü; hiçbir yerde bir değere ne
yazılıp ne yazılmadığı sorulmadı. `func main() {}` boş bir gövdeydi ve içinde hiçbir değişken
yoktu. Sıradaki ders bu boşluğu dolduruyor: bir değişkeni tanımlarken tipini yazmak zorunda
mısın, kısa bildirim tipi nereden çıkarıyor, ve sıralı bir sabit dizisinde yazılmayan değerleri
kim dolduruyor?
