---
title: 'Değişkenler ve Sabitler'
source: 'https://academia.sh/tr/kurslar/go-temelleri/degiskenler-ve-sabitler'
course: 'Go Temelleri'
language: tr
updated: '2026-08-23T14:25:01+00:00'
license: 'CC BY-SA 4.0'
---

# Değişkenler ve Sabitler

Kısa bildirim bir değişkenin tipini kaynakta hiç yazmadan belirliyor, altı sabitlik bir iota dizisinin yalnız ikisinde değer kaynakta yazılı — dördü bir önceki ifadenin tekrarından geliyor — ve aynı kısa bildirim satırı paket düzeyinde reddediliyor, fonksiyon içinde kabul ediliyor.

Önceki ders bir kaynağın çalışabilmesi için hangi parçaların zorunlu olduğunu ölçtü, ama
`func main() {}` boyunca gövde hep boştu — hiçbir değere ne yazılıp ne yazılmadığı hiç
sorulmadı. Bu ders o boşluğa giriyor. Bir değişken tanımlarken tipini yazmak zorunda mısın,
kısa bildirim yazmadığın tipi nereden çıkarıyor, ve sıralı bir sabit dizisinde aradaki
değerleri kim dolduruyor?

Programlama Temelleri kursu (M01/K02) değişken tanımını ve bağlamayı Python'la kurdu; orada
bir adın bir değere bağlanması tek bir yazımla oluyordu ve tip kaynakta hiç yer almıyordu.
**Bu kavram burada tekrar kurulmaz** — farkı tek cümleyle yazmak yeter: Go'da bir adın **bir
tipi vardır** ve bu tip ya yazılır ya da bir değerden çıkarılır; hiçbir değişken tipsiz
kalmaz. Bu dersin sorduğu soru, o çıkarımın nereden geldiğidir.

## Kısa Bildirim Tipi Nereden Çıkarıyor

Go'da bir değişken iki biçimde tanımlanır: `var ad tip = değer` ya da kısa bildirim, `ad :=
değer`. İkincisinde tip hiç yazılmaz; derleyici, atanan değerin **kendi** tipine bakarak
değişkenin tipini belirler. Bu, "yazılmayan bir şeyin tanımlı bir karşılığı var" örneklerinden
biridir — tip yazılmadı, ama değişkenin bir tipi olmaması diye bir seçenek yok, derleyici
o tipi değerden **çıkarıyor**.

Çıkarımın hangi tipe vardığını, çalışma zamanında `%T` biçim doğrulayıcısıyla sorabiliriz; bu
doğrulayıcı bir değerin **statik** tipinin adını yazdırır ve bu ad derleme zamanında sabitlenir
— her koşumda aynı yanıtı verir.

```go
// tur.go — kisa bildirimin cikardigi tip
package main

import "fmt"

func main() {
	tamsayi := 42
	kayanNokta := 3.14
	dizgi := "metin"
	mantiksal := true

	fmt.Printf("%-12s %-8s deger=%v\n", "tamsayi", fmt.Sprintf("%T", tamsayi), tamsayi)
	fmt.Printf("%-12s %-8s deger=%v\n", "kayanNokta", fmt.Sprintf("%T", kayanNokta), kayanNokta)
	fmt.Printf("%-12s %-8s deger=%v\n", "dizgi", fmt.Sprintf("%T", dizgi), dizgi)
	fmt.Printf("%-12s %-8s deger=%v\n", "mantiksal", fmt.Sprintf("%T", mantiksal), mantiksal)

	var genisTip float64 = 42
	fmt.Printf("%-12s %-8s deger=%v\n", "genisTip", fmt.Sprintf("%T", genisTip), genisTip)
}
```

```
tamsayi      int      deger=42
kayanNokta   float64  deger=3.14
dizgi        string   deger=metin
mantiksal    bool     deger=true
genisTip     float64  deger=42
```

**DT7.** `%T`, kaynağın kendisinden okunan statik bir addır; makineye, sürüme ya da koşuma
bağlı hiçbir bilgi taşımaz. Bu derste ve kursun geri kalanında tip adı okumak için hep bu
doğrulayıcı kullanılacak, çünkü ortama bağlı veri yasağını hiç ihlal etmiyor.

Bu, ölçüm için önemli bir ayrımı gösteriyor: `%T`nin yazdırdığı ad, bir bellek adresi ya da bir
değişkenin kendisi değil, derleyicinin o değişkene atadığı **tip bilgisinin adıdır**. İki farklı
koşumda aynı kaynak çalıştırıldığında `%T` her zaman aynı dizgiyi üretir, tıpkı bir önceki
derste `derlenirMi`nin her zaman aynı `derlendi`/`derlenmedi` yanıtını üretmesi gibi. Kursun
ölçüm araçlarının hepsi bu iki özelliği paylaşıyor: belirlenimci olmak ve ortama bağlı hiçbir
şey okumamak.

İlk dört satır, kısa bildirimin dört ayrı değerden dört ayrı tipe vardığını gösteriyor: tam
sayı yazınca `int`, ondalıklı yazınca `float64`, tırnak içinde yazınca `string`, `true`/`false`
yazınca `bool`. Hiçbirinde tip adı kaynakta geçmiyor; kısa bildirimin solundaki `:=` işareti,
"bu adın tipini sağdaki değerden çıkar" demenin kısaltmasıdır.

Bu çıkarım, atanan değerin **yazım biçimine** bakarak çalışıyor, çalışma zamanındaki bir
sınamaya değil. `42` yazıldığında derleyici bunun bir tam sayı sabiti olduğunu kaynağı okurken
görüyor; hiçbir değer üretilmeden, program hiç çalıştırılmadan bu karar veriliyor. Bu, kısa
bildirimin de bir derleme zamanı kararı olduğunu gösteriyor — yalnız tipin adı kaynakta
yazılmıyor, kararın kendisi hâlâ derleme sırasında, çalışma zamanından önce alınıyor. Kısa
bildirimin çalışma zamanına bıraktığı hiçbir şey yok; yazılmayan yalnızca **görünür harf
dizisidir**, karar değildir.

## `var` ile Yazılan Tip Nasıl Ayrılıyor

Beşinci satır farklı bir yol izliyor. `42` sayısı kısa bildirimle yazılsaydı `int` olurdu —
ilk satır bunu zaten gösterdi. Burada aynı `42` değeri, `var genisTip float64 = 42` satırıyla
**açıkça** `float64` yapılıyor. Kısa bildirim tipi değerden çıkarırken, `var` tipi elle
belirlemenin yolunu açıyor; ikisi arasındaki fark, kimin karar verdiğidir. Kısa bildirimde
karar değere aittir, `var`da karar yazan tarafa aittir.

Bu, önceki derste ölçülen örtük dönüşüm reddiyle karıştırılmamalı. `var genisTip float64 = 42`
bir dönüşüm değil, bir **ilk değer atamasıdır** — `42` burada tipsiz bir sabittir ve tipsiz
sabitler hedef tipe göre biçimlenir. Bir dönüşüm, zaten tipi belli olan bir **değişkeni** başka
bir değişkene atamaya çalıştığında devreye giriyordu (`var a int32 = 1; var b int64 = a`).
Aradaki fark ilerleyen derste tekrar ölçülecek; burada not edilmesi gereken, kısa bildirimin
sonucunu `var` ile bastırmanın bir ret değil, bir **tercih** olduğudur.

`var` yazımının bir üstünlüğü daha var: bir ilk değer olmadan da kullanılabiliyor.
`var sayac int` yazmak, sayacı hiçbir değer vermeden tanımlıyor ve derleyici bu satırı hiç
reddetmiyor — kısa bildirimin tersine, `var` bir değer istemez. Bu durumda değişkenin aldığı
değer, bu kursun ilerleyen bir dersinin konusu olan **sıfır değer**dir; burada yalnız şu not
edilsin: `var`ın tip yazmaya izin vermesi ile değer yazmadan da çalışabilmesi aynı kökten
geliyor — ikisi de, kısa bildirimin aksine, "bir değerden çıkarım" zorunluluğuna bağlı değil.

## Iota: Yazılmayan Sabit Değerleri Kim Dolduruyor

Sabitler, `const` ile tanımlanır ve bir grup içinde art arda sıralandığında `iota` adlı özel
bir sayaç kullanılabilir. `iota`, bir `const` bloğundaki her satırda sıfırdan başlayıp bir
artar; bir satırın kendi ifadesi yoksa, satır bir önceki satırın ifadesini **olduğu gibi**
tekrar eder ve yalnız `iota`nın değeri güncellenir.

Bunun çözdüğü bir sorun var: bir durum kümesini elle numaralandırmak (`Beklemede = 0`,
`Calisiyor = 1`, `Tamamlandi = 2`, ...) hem tekrar eden bir yazımdır hem de araya yeni bir
durum eklendiğinde bütün sayıların elle kaydırılmasını gerektirir. `iota`, bu numaralandırmayı
satırın **sırasına** bağlıyor; bir satır araya eklendiğinde ondan sonraki bütün değerler
otomatik kayar, hiçbiri elle güncellenmez. Bu, sayıların kendisinin önemli olmadığı, yalnız
**sırasının ve tekilliğinin** önemli olduğu durum kümeleri için kurulmuş bir düzenek.

```go
// sabitler.go — iota ile alti sabit, kacinin degeri kaynakta yazili
package main

import "fmt"

const (
	Beklemede  = iota
	Calisiyor
	Tamamlandi
	Basarisiz  = iota * 100
	Iptal
	ZamanAsimi
)

func main() {
	fmt.Printf("%-12s %d\n", "Beklemede", Beklemede)
	fmt.Printf("%-12s %d\n", "Calisiyor", Calisiyor)
	fmt.Printf("%-12s %d\n", "Tamamlandi", Tamamlandi)
	fmt.Printf("%-12s %d\n", "Basarisiz", Basarisiz)
	fmt.Printf("%-12s %d\n", "Iptal", Iptal)
	fmt.Printf("%-12s %d\n", "ZamanAsimi", ZamanAsimi)
}
```

```
Beklemede    0
Calisiyor    1
Tamamlandi   2
Basarisiz    300
Iptal        400
ZamanAsimi   500
```

**DT8.** Altı sabitin yalnız **ikisinde** (`Beklemede`, `Basarisiz`) bir ifade kaynakta
yazılı; dördünde (`Calisiyor`, `Tamamlandi`, `Iptal`, `ZamanAsimi`) satırda yalnız bir ad
duruyor, değer hiç yazılmıyor. Bu dördünün değeri iki kaynaktan geliyor: satırın kendi
sırasındaki `iota` değeri ve bir önceki satırdan **tekrarlanan** ifade.

Tablo bunu doğruluyor. `Calisiyor` ve `Tamamlandi`, `Beklemede`nin ifadesini (`iota`) tekrar
ediyor ama kendi satırlarındaki `iota` değeriyle (sırasıyla 1 ve 2) hesaplanıyor — bu yüzden
`0, 1, 2` diye artıyorlar. `Iptal` ve `ZamanAsimi` de aynı mantıkla `Basarisiz`in ifadesini
(`iota * 100`) tekrar ediyor, ama kendi `iota` değerleriyle (4 ve 5) çarpılıyor — `300, 400,
500` diye artıyorlar. `iota` bloğun tamamında **tek bir sayaçtır**; grup içinde ikinci bir
ifade göründüğünde sıfırlanmıyor, satır sırasına göre kesintisiz artmaya devam ediyor.

Bu davranış, "yazılmayanın karşılığı" sorusuna kursun şimdiye kadarki en dolaylı yanıtını
veriyor. Bir satırda hiçbir şey yazılmaması, o satırın **rastgele** ya da **boş** bir değer
alacağı anlamına gelmiyor; iki ayrı kural — sıradaki `iota` değeri ve bir önceki ifadenin
tekrarı — birleşip tam olarak tanımlı bir sonuç üretiyor. Yazılmayan dört değerin dördü de bu
yüzden `tanımlı` sınıfına giriyor, `açıkta` değil: sonuç koşumdan koşuma değişmiyor, kaynağı
okuyan biri kâğıt üzerinde de aynı sayılara ulaşabilir.

Bu örnekte her sabit `fmt.Printf` çağrısında kullanıldığı için kullanılmayan değişken reddiyle
karşılaşmıyoruz; ilk derste ölçülen kural burada da geçerli — bir sabit paket düzeyinde
tanımlandığında kullanılmama reddi zaten uygulanmıyor, çünkü Go bu reddi yalnız **yerel**
değişkenlere uyguluyor. Paket düzeyinde tanımlanan bir sabit ya da değişken, hiç okunmasa bile
derlemeyi durdurmaz. Bu ayrım bir sonraki bölümde tekrar karşımıza çıkacak.

Bu tek kural, ilk dersteki reddi hiç çelişmeden daraltıyor. İlk derste ölçülen "kullanılmayan
değişken" reddi, dört ret arasında en sık karşılaşılanıydı ve orada hangi bağlamda geçerli
olduğu hiç sorulmamıştı. Burada görülüyor ki o ret evrensel değil: yerel bir değişkeni
kullanmadan bırakmak reddedilir, paket düzeyinde bir sabiti kullanmadan bırakmak reddedilmez.
Bunun bir nedeni var — paket düzeyindeki bir sabit, aynı paketin başka bir dosyasında, hatta
başka bir paketten dışa aktarıldığında tamamen başka bir dosyada kullanılabilir; derleyici,
tek bir dosyayı okurken bu kullanımın ilerde başka bir yerde olup olmayacağını bilemez. Yerel
bir değişken ise fonksiyonun kendi gövdesiyle sınırlıdır ve derleyici onun kullanılıp
kullanılmadığını aynı bakışta görebilir.

`iota`nın bir de göz ardı etme yolu var: bir satırda ad yerine boş tanımlayıcı `_` yazılırsa,
`iota` yine artar ama o sıraya karşılık gelen hiçbir ad üretilmez. Bu, ilk derste ölçülen
boş tanımlayıcının bir başka kullanımı — orada kullanılmayan bir değeri **isimlendirmeden**
geçmenin yoluydu, burada sıradaki bir numarayı **atlamanın** yolu oluyor. İkisinde de aynı
sözcük, "bunu biliyorum ama bir ada bağlamayacağım" anlamına geliyor.

## Sınırlayıcı Ölçüm: Kısa Bildirim Her Yerde Çalışmaz

Kısa bildirim, göründüğü kadar evrensel değil. Bunu ölçmek için ilk dersteki derleyici
çağrısına dönüyoruz: aynı satırı iki farklı bağlamda deneyip sonucu sınıflayacağız.

```go
// derleyici.go — derleyiciyi program icinden cagiran yardimci
package main

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

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 sinif(ok bool) string {
	if ok {
		return "derlendi"
	}
	return "derlenmedi"
}
```

Aynı `x := 5` satırını iki farklı bağlamda deneyelim: bir kez bir fonksiyonun dışında, paket
düzeyinde; bir kez bir fonksiyonun içinde.

```go
// sinirlayici.go — kisa bildirim paket duzeyinde reddedilir mi
package main

import "fmt"

func main() {
	paketDuzeyi := `package sinama
x := 5
func F() { _ = x }`
	fonksiyonDuzeyi := `package sinama
func F() { x := 5; _ = x }`

	fmt.Printf("%-24s %s\n", "paket duzeyinde", sinif(derlenirMi(paketDuzeyi)))
	fmt.Printf("%-24s %s\n", "fonksiyon icinde", sinif(derlenirMi(fonksiyonDuzeyi)))
}
```

```
paket duzeyinde          derlenmedi
fonksiyon icinde         derlendi
```

**DT9.** İki kaynak da aynı `x := 5` satırını taşıyor; tek fark, satırın bir fonksiyon
gövdesinin içinde mi dışında mı durduğudur. Derleyici, kısa bildirimi yalnız bir fonksiyon
gövdesinin içinde geçerli bir **ifade** sayıyor; paket düzeyinde beklediği şey `var` ya da
`const` gibi bir bildirim başlığıdır, `:=` değil.

Bu sınır, kısa bildirimin neden "kolay yol" değil, **bağlama özgü bir kısaltma** olduğunu
gösteriyor. Kısa bildirim, bir fonksiyonun içinde art arda birçok değişken tanımlarken `var`
sözcüğünü ve tip adını tekrar tekrar yazmaktan kurtarıyor; paket düzeyinde ise bu kısaltmaya
gerek yok, çünkü paket düzeyindeki bildirimler zaten çoğunlukla tek tek, `var` ya da `const`
ile yazılıyor ve bunların ilklendirme sırası dosya sırasına değil, bağımlılık sırasına göre
çözülüyor — bu çözüm bir sonraki derste temel tipler üzerinden tekrar görülecek.

Bu satırın reddi, ilk dersteki dört retten farklı bir sınıfa ait. Orada reddedilen dört kaynak
sözdizimi açısından geçerliydi, yalnız derleyici belirli bir kalıbı **istemiyordu**. Burada
`x := 5` satırı paket düzeyinde sözdizimi açısından **geçersizdir** — dilin grameri, `:=`
işaretini yalnız bir ifade bağlamında tanıyor, paket düzeyi bir ifade bağlamı değil, bir
bildirim listesidir. Bu, "reddedildi" sınıfının kendi içinde iki alt türü olduğunu gösteriyor:
bir kalıp gramer açısından geçerli ama derleyici tarafından **istenmiyor** olabilir (ilk
dersteki dört ret), ya da kalıbın kendisi o bağlamda **hiç tanımlı değildir** (bu dersteki
ret). İkisi de aynı `derlenmedi` yanıtını üretiyor, ama biri bir kural ihlali, öbürü bir
gramer uyumsuzluğu.

Bu ayrımın pratik sonucu, paket düzeyinde bir değer tanımlamak istendiğinde yazım biçiminin
**değişmesi** gerektiğidir — kısa bildirimden `var`a geçmek bir tercih değil, bir zorunluluktur.
Bir fonksiyonun içinden paket düzeyine taşınan bir satır, yalnız yerini değiştirmekle kalmaz;
yazımını da değiştirmek zorunda kalır.

Bu dersin üç ölçümü — kısa bildirimin tip çıkarımı, `iota`nın sabit doldurması, kısa bildirimin
paket düzeyindeki reddi — aynı sorunun üç ayrı yüzü. Üçünde de yazılmayan bir şey var: bir tip
adı, dört sabit değeri, bir bildirim biçiminin geçerliliği. Üçünde de dil, bu boşluğu rastgele
bırakmıyor: birinde değere bakarak dolduruyor, birinde bir sayaç ve bir tekrar kuralıyla
dolduruyor, birinde ise dolduracak hiçbir şey bulamayıp reddediyor. Kursun ilk iki dersi
"nelerin reddedildiğini" ve "nelerin zorunlu olduğunu" ölçtü; bu ders, reddedilmeyen ve
zorunlu da olmayan bir ara bölgeyi — **çıkarımı** — ölçüyor.

## Özet

- Kısa bildirim (`:=`), bir değişkenin tipini kaynakta hiç yazmadan, atanan değerin kendi
  tipinden çıkarır.
- `var ad tip = değer` yazımı, çıkarımın sonucunu yazan tarafın **elle** belirlemesine izin
  verir; bu bir dönüşüm değil, bir ilk değer atamasıdır.
- Altı sabitlik bir `iota` dizisinde yalnız ikisinin değeri kaynakta yazılıdır; dördü, satırın
  kendi `iota` değeriyle bir önceki ifadenin tekrarından üretilir.
- `iota`, bir `const` bloğunun tamamında tek bir sayaçtır ve ikinci bir ifade göründüğünde
  sıfırlanmaz.
- Aynı kısa bildirim satırı, bir fonksiyon gövdesinin içinde derlenirken paket düzeyinde
  reddedilir — kısa bildirim yalnız fonksiyon içinde geçerli bir ifadedir.

## Sonraki Adım

Bu derste bir değişkenin tipi hep bir **değerden** çıkarıldı — `42`den `int`, `3.14`ten
`float64`. Ama bu tiplerin kendileri hiç sorgulanmadı: bir tam sayı taştığında ne oluyor, iki
kayan noktalı değer karşılaştırıldığında ne bekleniyor, ve `rune` denen tip aslında neyin
karşılığı? Sıradaki ders temel tipleri, her birinin yazılmayan bir durumda ne yaptığını
ölçerek ele alıyor.
