---
title: 'Sıfır Değerler'
source: 'https://academia.sh/tr/kurslar/go-temelleri/sifir-degerler'
course: 'Go Temelleri'
language: tr
updated: '2026-08-23T14:25:01+00:00'
license: 'CC BY-SA 4.0'
---

# Sıfır Değerler

On beş yazılmamışlık tek bir çerçeveden geçiriliyor: sekizi dil tarafından tanımlı bir karşılık buluyor, dördü derleyici tarafından reddediliyor, üçü çalışma zamanına açık kalıyor. Sınırlayıcı ölçüm: nil bir dilime eklenebiliyor ama nil bir sözlüğe yazılamıyor — ikisi de aynı biçimde sıfır değer.

Önceki ders `var b int8` yazıp hiç değer vermeseydik ne olacağını sormadan bitti. Bu soru,
kursun açılışından beri ertelenen asıl soru: bir değişken ilk değeri verilmeden bırakıldığında
dil orada ne buluyor? Bu ders bu soruyu tek bir örnekte değil, on beş ayrı yerde soruyor ve
üç sınıftan birine yazıyor — **tanımlı**, dil yazılmayanın yerine bir değer koyuyor;
**reddedildi**, derleyici yazılmamış olmayı kabul etmiyor; **açıkta**, sonuç çalışma zamanına
kalıyor. Kursun geri kalanı boyunca atıf yapılacak sayılar burada üretiliyor.

Programlama Temelleri kursu (M01/K02) bir değişkenin bir adla bağlanmasını Python'la kurdu;
orada bir ad, bir değer verilmeden var olamazdı. **Bu kavram burada tekrar kurulmaz** — farkı
tek cümleyle yazmak yeter: Go'da bir değişken değer verilmeden de var olabiliyor, çünkü tip
sistemi her tipe önceden bir **sıfır değer** atamış durumda. Bu dersin ölçtüğü, o sıfır
değerin her tipte ne olduğu ve her durumda gerçekten "orada" olup olmadığıdır.

## Kurgu

Go'da bir programı okurken en çok işe yarayan soru, yazılanın ne yaptığı değil, yazılmayanın
ne olduğudur. İlk değeri verilmeyen her değişkenin tanımlı bir değeri var, kullanılmayan bir
değişken derlemeyi durduruyor, olmayan bir anahtar iki yanıt birden dönüyor, hiç argüman
verilmeyen bir değişken argüman listesi boş bir dilim oluyor. Aynı dilde, yazılmayan bazı
şeylerin karşılığı hiç yok ve program çalışırken duruyor.

Ölçüm bu üçlüyü tek bir soruya indiriyor: her yazılmamışlık için, dil bir şey mi koyuyor,
derleyici mi reddediyor, yoksa sonuç açıkta mı kalıyor? Yanıtı bulmanın ikinci yarısı
derleyiciyi **program içinden** çağırıyor: bir kaynak parçası geçici bir pakete yazılıyor,
derleyici koşturuluyor ve yalnız geçip geçmediği okunuyor — hata metni hiç okunmuyor, çünkü
ölçülen şey "neden reddedildi" değil, "reddedildi mi".

## Çekirdek: Üç Sınıfa Ayıran Bir Gözlemci

```go
// eksik.go — yazilmayan sey ne oluyor: dil tanimli bir sey mi koyuyor, derleyici mi reddediyor, yoksa acikta mi kaliyor
package main

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

var tanimli, reddedildi, acikta int

func gozle(ad, sinif, kanit string) {
	switch sinif {
	case "tanimli":
		tanimli++
	case "reddedildi":
		reddedildi++
	default:
		acikta++
	}
	fmt.Printf("%-38s %-11s %s\n", ad, sinif, kanit)
}

func ozet() {
	fmt.Printf("yazilmayan: %d tanimli, %d reddedildi, %d acikta\n", tanimli, reddedildi, acikta)
}

func derlenirMi(kaynak string) bool {
	dizin, err := os.MkdirTemp("", "sinama")
	if err != nil {
		return false
	}
	defer os.RemoveAll(dizin)
	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 panikliyorMu(f func()) (p bool) {
	defer func() {
		if recover() != nil {
			p = true
		}
	}()
	f()
	return false
}
```

**DT13.** `gozle`, her gözlemi bir sınıfa yazan tek giriş noktasıdır; sayaçları tutan üç
paket düzeyi değişken (`tanimli`, `reddedildi`, `acikta`) yalnız burada artıyor, böylece
`ozet` çağrıldığında toplamlar hep gözlemlerle tutarlı kalıyor.

**DT14.** `panikliyorMu`, bir işlevi çalıştırıp panikleyip paniklemediğini `recover` ile
yakalıyor ve yalnız `panik=true`/`panik=false` döndürüyor — hiçbir yığıt izi basılmıyor. Bu,
kursun panik ölçen her yerinde geçerli tek yöntem.

Bu iki yardımcı işlev, dersin ölçtüğü üç sınıfın her birine bir araç sağlıyor: `gozle` ve
`ozet` sınıflandırmayı ve toplamı tutuyor, `panikliyorMu` açıkta kalan davranışı yakalıyor,
`derlenirMi` (bir önceki bölümde tanımlı) reddi ölçüyor. Üçü birlikte, on beş satırlık ölçümün
gövdesini tek bir çağrı biçimine indiriyor: her satır `gozle`ye bir ad, bir sınıf ve bir kanıt
veriyor, geri kalan her şeyi bu üç yardımcı hallediyor.

## On Beş Yazılmamışlık

```go
// olcum.go — on bes yazilmamislik, uc sinifa bolunur
package main

import "fmt"

type Kayit struct {
	Ad    string
	Sayi  int
	Etkin bool
}

func adliDonus() (sonuc int, hata error) { return }

func degisken(sayilar ...int) []int { return sayilar }

func main() {
	fmt.Println("-- yazilmayanin karsiligi --")

	var tamsayi int
	gozle("ilk deger verilmeyen tam sayi", "tanimli", fmt.Sprint(tamsayi))

	var dilim []int
	gozle("ilk deger verilmeyen dilim", "tanimli",
		fmt.Sprint("nil=", dilim == nil, " uzunluk=", len(dilim), " eklenebilir=", append(dilim, 1)))

	var esleme map[string]int
	gozle("ilk deger verilmeyen eslemeden okuma", "tanimli", fmt.Sprint(esleme["yok"]))

	yazmaPanikledi := panikliyorMu(func() { esleme["yeni"] = 1 })
	gozle("ilk deger verilmeyen eslemeye yazma", "acikta", fmt.Sprint("panik=", yazmaPanikledi))

	var isaretci *Kayit
	okumaPanikledi := panikliyorMu(func() { _ = isaretci.Sayi })
	gozle("ilk deger verilmeyen isaretciden okuma", "acikta", fmt.Sprint("panik=", okumaPanikledi))

	var kayit Kayit
	gozle("yazilmayan yapi alanlari", "tanimli", fmt.Sprintf("%q %d %t", kayit.Ad, kayit.Sayi, kayit.Etkin))

	s, h := adliDonus()
	gozle("adlandirilmis donusun yazilmamasi", "tanimli", fmt.Sprint(s, " ", h == nil))

	gozle("degisken argumana hic arguman", "tanimli",
		fmt.Sprint("nil=", degisken() == nil, " uzunluk=", len(degisken())))

	kaynak := []int{10, 20, 30, 40}
	gozle("dilim sinirlarinin yazilmamasi", "tanimli", fmt.Sprint(kaynak[:], " ", kaynak[1:], " ", kaynak[:2]))

	deger, varMi := esleme["yok"]
	gozle("olmayan anahtarin iki yanit vermesi", "tanimli", fmt.Sprint(deger, " ", varMi))

	metin := "çay"
	gozle("dizgide karakter yerine bayt", "acikta",
		fmt.Sprint("uzunluk=", len(metin), " ilk=", metin[0], " rune=", len([]rune(metin))))

	gozle("kullanilmayan degisken", siniflaKaynak(`package sinama
func F() { x := 1 }`), "")

	gozle("kullanilmayan ice aktarim", siniflaKaynak(`package sinama
import "fmt"
func F() {}`), "")

	gozle("donus degerinin yazilmamasi", siniflaKaynak(`package sinama
func F() int { }`), "")

	gozle("ortuk tip donusumu", siniflaKaynak(`package sinama
func F() { var a int32 = 1; var b int64 = a; _ = b }`), "")

	ozet()
}

func siniflaKaynak(kaynak string) string {
	if derlenirMi(kaynak) {
		return "acikta"
	}
	return "reddedildi"
}
```

```
-- yazilmayanin karsiligi --
ilk deger verilmeyen tam sayi          tanimli     0
ilk deger verilmeyen dilim             tanimli     nil=true uzunluk=0 eklenebilir=[1]
ilk deger verilmeyen eslemeden okuma   tanimli     0
ilk deger verilmeyen eslemeye yazma    acikta      panik=true
ilk deger verilmeyen isaretciden okuma acikta      panik=true
yazilmayan yapi alanlari               tanimli     "" 0 false
adlandirilmis donusun yazilmamasi      tanimli     0 true
degisken argumana hic arguman          tanimli     nil=true uzunluk=0
dilim sinirlarinin yazilmamasi         tanimli     [10 20 30 40] [20 30 40] [10 20]
olmayan anahtarin iki yanit vermesi    tanimli     0 false
dizgide karakter yerine bayt           acikta      uzunluk=4 ilk=195 rune=3
kullanilmayan degisken                 reddedildi  
kullanilmayan ice aktarim              reddedildi  
donus degerinin yazilmamasi            reddedildi  
ortuk tip donusumu                     reddedildi  
yazilmayan: 8 tanimli, 4 reddedildi, 3 acikta
```

Son dört satır, ilk derste ayrıntılı ölçülen dört rettir; burada listenin tamamlayıcısı olarak
yer alıyor ve aynı sınıfa (`reddedildi`) düşüyor. Geri kalan on bir satır bu derse özgü ve altı
ayrı tipi kapsıyor: tam sayı, dilim, sözlük, işaretçi, yapı, isimlendirilmiş dönüş değeri,
değişken sayıda argüman, dizgi. Her satır aynı soruyu tek bir tipe soruyor — bu tipin ilk
değeri verilmediğinde ne oluyor — ve yanıtı `gozle`ye üç parçayla teslim ediyor: bir ad, bir
sınıf, bir kanıt. Kanıt sütunu, iddiayı doğrulayan gerçek değerleri taşıyor; bir sonraki bölüm
bu kanıtları tek tek okuyor.

## Sayıların Okunması

**Birinci iddia: Go'da "başlatılmamış" diye bir durum yok.** On beş yazılmamışlığın **sekizinde**
dil yazılmayanın yerine tanımlı bir şey koyuyor: bir tam sayının sıfır değeri `0`, bir dilimin
sıfır değeri `nil` ama uzunluğu `0` ve eklenebilir, bir sözlükten okuma `0` dönüyor, bir yapının
alanları kendi sıfır değerlerini taşıyor, adlandırılmış bir dönüş yazılmadığında `0` ve `nil`
dönüyor, değişken sayıda argümana hiç argüman verilmediğinde parametre `nil` bir dilim oluyor,
dilim sınırları yazılmadığında baştan ve sona kadar uzanıyor, olmayan bir anahtar `0` ve
`false` dönüyor. Sekizi de bir kolaylık değil bir sözleşme: okuyan taraf ne bulacağını
kaynağa bakmadan bilir.

Bu sekizinin ortak yanı, sıfır değerin **tip başına** farklı görünmesi ama her zaman
öngörülebilir olması. Bir tam sayı için sıfır değer sayısal sıfırdır; bir dizgi için boş
dizgidir (`""`); bir mantıksal değer için `false`tur; bir işaretçi, dilim, sözlük ya da işlev
için `nil`dir. Dördü de aynı sözcükle (`nil`) anılmasa da aynı fikri taşıyor: "henüz hiçbir
şeye bağlı değil". `nil`in kendisi tek bir değer değildir — bir işaretçinin `nil`i bellekte
hiçbir adresi göstermediği, bir dilimin `nil`i hiçbir alt diziye sahip olmadığı, bir sözlüğün
`nil`i hiçbir depolama alanı ayrılmadığı, bir işlevin `nil`i çağrılabilecek hiçbir kod
bulunmadığı anlamına geliyor. Dördü de aynı sözcükle yazdırılıyor ama dördü de kendi tipinin
içinde ayrı bir yokluğu temsil ediyor.

**İkinci iddia: derleyicinin reddettiği dört şeyin dördü de başka dillerde uyarı düzeyindedir.**
Kullanılmayan değişken, kullanılmayan içe aktarım, dönüş değerinin yazılmaması, örtük tip
dönüşümü — dördü de kaynağı derlenmez yapıyor. Reddetmek bir katılık gösterisi değil,
yazılmayanın karşılığını **daraltma** kararı: dil bu dört durumda "tanımlı bir şey koymak"
yerine "hiç izin vermemek"i seçiyor.

Bu dördü, ilk sekizle karşılaştırıldığında ilginç bir yer değiştirme gösteriyor. İlk sekizde
dil, yazılmayan bir şeye rağmen kaynağı çalıştırmaya izin veriyor ve boşluğu kendi dolduruyor.
Bu dört durumda ise dil, boşluğu doldurmak yerine kaynağı hiç çalıştırmıyor. İkisi de
"yazılmayanın karşılığı" olsa da, biri çalışma zamanına taşınan bir değer, öbürü derleme
zamanında kapanan bir kapı.

**Üçüncü iddia: tanımlılık okuma yönünde çalışıyor, yazma ve yorumlama yönünde bitiyor.**
Açıkta kalan üç durumun üçü de bunu gösteriyor. İlk değeri verilmeyen bir sözlükten **okumak**
tanımlıdır ama ona **yazmak** programı durduruyor — panik. İlk değeri verilmeyen bir işaretçi
tanımlı bir değerdir (`nil`) ama **okunduğunda** durur — yine panik. Bir dizginin uzunluğu
tanımlıdır ama indekslendiğinde gelen şey karakter değil **bayttır** — `"çay"` dört bayt, üç
`rune` ve ilk bayt `195` (bir çok baytlı kodlamanın ilk parçası, tek başına bir harf değil).

## Sınırlayıcı Ölçüm: "Tanımlı" Kullanışlı Demek Değildir

Sekiz tanımlı satırın hepsi aynı derecede kullanışlı değil. İkinci satır (`nil` dilim) ile
dördüncü satır (`nil` sözlük) karşılaştırılırsa fark netleşiyor: ikisi de ilk değeri verilmemiş
ve ikisi de `nil`. Ama `nil` dilime `append` çalışıyor — çıktıda `eklenebilir=[1]` görünüyor —
`nil` sözlüğe yazma ise panikliyor. Aynı sözcük (`nil`), aynı sınıf (`tanımlı`), iki farklı
sonuç.

**DT15.** Fark, `nil`in kendisinde değil, dilin bu iki tip için verdiği **ayrı sözde**. Bir dilim, `nil`
olsa bile bir uzunluk (`0`) ve bir kapasite (`0`) taşıyan bir başlıktır; `append` bu başlığa
yeni bir alt dizi ayırıp genişleyebilir, çünkü genişleme dilimin zaten sahip olduğu bir
davranıştır. Bir sözlük ise `nil` olduğunda hiçbir depolama alanı içermiyor; okuma bu boşlukla
başa çıkabiliyor (aranan anahtar zaten yoktur, sıfır değeri dönülür) ama yazma yeni bir girdi
için yer ayırmayı gerektiriyor ve `nil` sözlüğün ayıracak hiçbir yeri yok. "Tanımlı" sözcüğü
ikisinde de doğru, ama **neyin** tanımlı olduğu tipten tipe değişiyor.

Bu, sekiz tanımlı satırı okurken akılda tutulması gereken bir uyarı: bir değerin sıfır değeri
olması, o değerin **her işlemi** kaldırabileceği anlamına gelmiyor. Hangi işlemlerin sıfır
değerle çalıştığı, kursun sıradaki konusunda dilim ve sözlük tipleri ayrı ayrı ele alınırken
tekrar ölçülecek.

Aynı sınırlayıcı okuma, açıkta kalan üçüncü satırda da bir kez daha görünüyor. İşaretçinin
sıfır değeri de `nil`dir ve `nil` dilim gibi bazı işlemleri kaldırıyor — bir `nil` işaretçiyi
başka bir işaretçiyle karşılaştırmak ya da yeniden atamak sorunsuz çalışıyor. Ama alan okumak
(`isaretci.Sayi`) çalışmıyor, çünkü okunacak bir alan için önce bir yapı örneğinin var olması
gerekiyor ve `nil` işaretçi hiçbir örneği göstermiyor. Üç tip — dilim, sözlük, işaretçi — üçü
de `nil`i sıfır değeri olarak taşıyor ama üçü de kendi davranış kümesini kendisi tanımlıyor;
tek bir "nil kuralı" yok, tip başına ayrı bir sözleşme var.

## Kör Nokta: Redd Nedeni Ölçülmüyor

Dört ret satırı `derlenirMi`nin `true`/`false` yanıtına dayanıyor ve hata metni hiç okunmuyor.
Bunun bir bedeli var: bir kaynak, ölçülmek istenenden **başka** bir nedenle de reddedilmiş
olabilir ve ölçüm bunu ayırt edemez. Bu yüzden kural şu — reddedilen her kaynak parçası, tek
bir yazılmamışlık dışında derlenebilir olmalı; kullanılmayan değişken örneğinde `x := 1`
dışında hiçbir sorun yok, dönüş değeri örneğinde `func F() int { }` dışında hiçbir sorun yok.
Bu koşul elle kurulup doğrulandı; ölçüm aracı bunu kendisi denetlemiyor.

**DT16.** Bu, ölçümün yönteminden gelen bilinçli bir sınırlama, bir gözden kaçırma değil.
`derlenirMi` yalnız `cmd.Run()`in çıkış durumunu okuyor; hata metnini okumamak, hem sürüme
bağlı veri yasağını hem de "neden değil, ne" sorusunu koruyor. Bedeli, bu dersteki dört
kaynağın **elle** doğrulanmış olmasıdır — her biri yazılırken tek bir değişiklik denendi ve
geri kalan her şeyin sabit tutulduğu kontrol edildi. Kursun geri kalanında derleyici reddi
ölçülen her yerde aynı disiplin sürüyor.

Sekiz satırlık tanımlı grubun da benzer bir kör noktası var: `gozle` işlevi, kendisine verilen
kanıtı olduğu gibi yazdırıyor, doğruluğunu sınamıyor. Bir satırın gerçekten "tanımlı" sınıfına
ait olup olmadığı, kod yazılırken elle karar veriliyor — çerçeve yalnız bu kararı **saydırıyor**,
kendisi üretmiyor. Kâhin (hangi yazılmamışlığın hangi sınıfa girdiği bilgisi) programın dışında,
bu dersi yazan tarafın elinde.

## Özet

- On beş yazılmamışlığın **8'i tanımlı, 4'ü reddedildi, 3'ü açıkta** — kursun bağlayıcı
  dağılımı burada üretildi.
- Go'da "başlatılmamış" diye bir durum yok: sekiz tanımlı satırın her biri, dilin yazılmayanın
  yerine koyduğu somut bir değer taşıyor.
- Derleyicinin reddettiği dört şey, çalışma zamanında zararsız olsa da yazılmayanın karşılığını
  daraltma kararıyla derlemeyi durduruyor.
- Tanımlılık okuma yönünde çalışıyor, yazma ve yorumlama yönünde bitiyor: `nil` sözlükten
  okumak tanımlı, yazmak panik; dizginin uzunluğu tanımlı, indekslemesi bayt veriyor.
- `nil` dilim ile `nil` sözlük aynı sözcüğü taşısa da aynı işlemleri kaldırmıyor — `nil` dilime
  eklenebiliyor, `nil` sözlüğe yazılamıyor.

## Sonraki Adım

Sıfır değerler, bir değişkenin **hiç dokunulmadığında** ne olduğunu ölçtü. Ama bir program
neredeyse hiçbir zaman değişkenlere dokunmadan durmuyor — dallanıyor, döngü kuruyor, bir
durumdan diğerine geçiyor. Sıradaki ders denetim akışına bakıyor: `for` neden koşulsuz
yazılabiliyor, `switch` neden ifadesiz yazılabiliyor, ve bir dalın sonunda yazılmayan `break`
neyin yerini tutuyor?
