---
title: 'Tip İddiası ve Tip Anahtarı'
source: 'https://academia.sh/tr/kurslar/go-tip-sistemi/tip-iddiasi-ve-tip-anahtari'
course: 'Arayüzler, Hatalar ve Genellikler'
language: tr
updated: '2026-08-23T14:25:02+00:00'
license: 'CC BY-SA 4.0'
---

# Tip İddiası ve Tip Anahtarı

Beş değerden ikisi bir arayüzü karşılıyor; tip iddiasının iki yanıtlı biçimi bunu panik olmadan sayıyor, tek yanıtlı biçim başarısız olduğunda panikliyor ve panik yalnız panik=true olarak okunuyor. Tip anahtarı aynı beş değeri kendi dallarına dağıtıyor. Sınırlayıcı ölçüm: aynı değer hem bir somut tip dalına hem bir arayüz dalına uyabiliyor, ve seçilen dal yazılış sırasına bağlı — ders bunu iki sıralamayla koşturuyor.

Önceki ders boş arayüzün bir değerin tip bilgisini kaybetmeden taşıdığını ölçtü, ama o
bilgiye yalnız `%T` ile, salt okuma amacıyla baktı. Bu bilginin gerçek kullanımı okumak değil
sormaktır: bu değer şu arayüzü karşılıyor mu, ve karşılıyorsa asıl değeri bana ver. Go bu
soruyu iki ayrı yapıyla soruyor — **tip iddiası** tek bir aday hakkında soruyor, **tip
anahtarı** birden çok aday arasından seçim yapıyor. İkisi de değere soruyor, ikisi de aynı
çiftin (tip, değer) içine bakıyor.

İkisinin de sorduğu şey, ilk dersteki on altı bağın en sık tekrarlanan kalıbı: bir bağ
kaynakta yazılı değilse ve derleyici onu kullanım anında kurmuyorsa, geriye tek yol
kalıyor — çalışma zamanında değerin kendisine sormak. Bu ders o sormanın iki biçimini,
sonuçlarını ve bir tanesinin taşıdığı riski ölçüyor.

## Tip İddiasının İki Yanıtlı Biçimi

Bir tip iddiası `deger.(Tip)` biçiminde yazılıyor ve iki biçimi var. Tek yanıtlı biçim
(`v := deger.(Tip)`) yalnız değeri döndürüyor; iddia yanlışsa çalışma zamanı hatası veriyor.
İki yanıtlı biçim (`v, tamam := deger.(Tip)`) ikinci bir mantıksal değer döndürüyor;
iddia yanlışsa `tamam` `false` oluyor ve program durmuyor.

`Tip` yerine yazılan şey iki ayrı soru sorabiliyor. Somut bir tip yazıldığında ("bu değerin
dinamik tipi tam olarak bu mu") karşılaştırma dinamik tipin kendisine bakıyor. Bir arayüz
yazıldığında ("bu değer bu sözleşmeyi karşılıyor mu") karşılaştırma yöntem kümesine bakıyor.
İkisi de aynı `deger.(Tip)` yazımını paylaşıyor; hangi soru sorulduğu yalnız `Tip`in kendi
doğasından, somut mu arayüz mü olduğundan, anlaşılıyor. Aşağıdaki ölçüm bir arayüz sorusu
soruyor: beş ayrı değeri aynı arayüze karşı sınıyor ve kaçının karşıladığını sayıyor.

```go
// bes-soru.go — bes degerden kaci Depolayici arayuzunu karsiliyor
package main

import "fmt"

type Depolayici interface{ Depola() string }

type DiskKaydi struct{}

func (DiskKaydi) Depola() string { return "disk" }

type BellekKaydi struct{}

func (BellekKaydi) Depola() string { return "bellek" }

type Gecici struct{}

func main() {
	degerler := []any{DiskKaydi{}, 42, BellekKaydi{}, "metin", Gecici{}}
	dogruSayisi := 0
	for i, d := range degerler {
		depo, tamam := d.(Depolayici)
		if tamam {
			fmt.Printf("deger#%d dinamik_tip=%T Depolayici_mi=%t cagri=%s\n", i, d, tamam, depo.Depola())
			dogruSayisi++
			continue
		}
		fmt.Printf("deger#%d dinamik_tip=%T Depolayici_mi=%t\n", i, d, tamam)
	}
	fmt.Println("bes sorudan dogru sayisi:", dogruSayisi)
}
```

```
deger#0 dinamik_tip=main.DiskKaydi Depolayici_mi=true cagri=disk
deger#1 dinamik_tip=int Depolayici_mi=false
deger#2 dinamik_tip=main.BellekKaydi Depolayici_mi=true cagri=bellek
deger#3 dinamik_tip=string Depolayici_mi=false
deger#4 dinamik_tip=main.Gecici Depolayici_mi=false
bes sorudan dogru sayisi: 2
```

Beş değerden ikisi (`DiskKaydi`, `BellekKaydi`) `Depolayici`yi karşılıyor, üçü (`int`,
`string`, `Gecici`) karşılamıyor. `Gecici` bir yapı olduğu hâlde karşılamıyor, çünkü `Depola`
yöntemini hiç yazmamış — arayüz karşılamasının koşulu yapı olmak değil, yöntem kümesinin
eşleşmesi. `tamam` değişkeni bu beş sorunun her birine kesin bir yanıt veriyor ve döngü hiçbir
noktada durmuyor; bu, iki yanıtlı biçimin asıl gücü.

`depo` değişkeni bu ölçümün ikinci yarısını taşıyor. Tip iddiası yalnız "karşılıyor mu"
sorusuna yanıt vermiyor; `tamam` doğruysa `depo` artık statik tipi `Depolayici` olan,
`Depola` yöntemi çağrılabilir gerçek bir değer. `cagri=disk` ve `cagri=bellek` sütunları bu
değerin gerçekten kullanılabilir olduğunu gösteriyor — önceki dersteki "doğrudan
çağrılamaz" bedeli burada tam olarak geri ödeniyor: tip iddiası başarılı olduğunda değer,
boş arayüzün kapattığı erişimi yeniden açıyor.

**AR7.** Beş değer bilinçli olarak üç farklı başarısızlık nedeninden seçildi: `int` ve
`string` hiç yöntem taşımıyor, `Gecici` bir yapı ama yanlış (boş) yöntem kümesine sahip.
Üçü de aynı `false` yanıtını veriyor ama nedenleri farklı — ölçüm bu farkı ayırt etmiyor,
yalnız karşılayıp karşılamadığını sayıyor.

İki yanıtlı biçim başarısız olduğunda ilk değişken (`depo`) rastgele bir şey değil, hedef
tipin kendi sıfır değeri oluyor — burada `Depolayici` bir arayüz olduğu için sıfır değeri
`nil`. Bu, önceki iki dersin bağladığı bir noktayı bir kez daha doğruluyor: Go'da yazılmayan
ya da başarısız olan bir şeyin karşılığı asla tanımsız kalmıyor, her zaman kendi tipinin
sıfır değeri devreye giriyor.

## Tek Yanıtlı Biçim Başarısız Olduğunda: Panik

İki yanıtlı biçim başarısızlığı bir değere çeviriyor; tek yanıtlı biçim aynı başarısızlığı
bir panige çeviriyor. Aşağıdaki ölçüm bunu doğrudan koşturuyor.

```go
// panik-olcumu.go — tek yanitli tip iddiasi basarisiz oldugunda panikliyor
package main

import "fmt"

type Depolayici interface{ Depola() string }

type DiskKaydi struct{}

func (DiskKaydi) Depola() string { return "disk" }

func panikliyorMu(f func()) (p bool) {
	defer func() {
		if recover() != nil {
			p = true
		}
	}()
	f()
	return false
}

func main() {
	var basarili any = DiskKaydi{}
	var basarisiz any = 42

	fmt.Println("basarili tek yanitli panikliyor mu :", panikliyorMu(func() {
		_ = basarili.(Depolayici)
	}))
	fmt.Println("basarisiz tek yanitli panikliyor mu :", panikliyorMu(func() {
		_ = basarisiz.(Depolayici)
	}))
	fmt.Println("basarisiz iki yanitli panikliyor mu :", panikliyorMu(func() {
		_, tamam := basarisiz.(Depolayici)
		_ = tamam
	}))
}
```

```
basarili tek yanitli panikliyor mu : false
basarisiz tek yanitli panikliyor mu : true
basarisiz iki yanitli panikliyor mu : false
```

Üç satır aynı `basarisiz` değeri (bir `int`) sınıyor, yalnız çağrı biçimi değişiyor. Tek
yanıtlı biçim `DiskKaydi{}` için panik üretmiyor, çünkü iddia gerçekten doğru. Aynı biçim
`42` için panikliyor, çünkü `int` `Depolayici`yi karşılamıyor ve tek yanıtlı biçim bu
durumda çalışma zamanı hatası fırlatıyor — `panikliyorMu` bu hatayı `recover` ile yakalayıp
yalnız `panik=true` olarak okuyor, yığıt izi hiç basılmıyor. Üçüncü satır aynı başarısız
iddiayı iki yanıtlı biçimle deniyor ve panik hiç oluşmuyor; `tamam` sessizce `false` oluyor.
Fark biçimde: aynı soru, iki ayrı sonuç sözleşmesi.

**AR8.** `panikliyorMu` burada Go Temelleri kursunun `eksik.go` çerçevesinden aynı işlevle
yeniden kuruldu: bir işlevi çalıştırıp panikleyip paniklemediğini `recover` ile yakalıyor ve
yalnız iki değerden birini döndürüyor. Bu, kursun panik ölçen her yerinde geçerli tek yöntem.

Bu iki değerlik örnek tek başına yeterli değil: beş değerin tamamı tek yanıtlı biçimden
geçirilirse, panikleyenlerin sayısı önceki bölümdeki `false` sayısıyla aynı çıkmalı — ikisi
aynı olguyu iki ayrı sözleşmeden okuyor.

```go
// panik-sayimi.go — bes degerin kaci tek yanitli bicimde panikliyor
package main

import "fmt"

type Depolayici interface{ Depola() string }

type DiskKaydi struct{}

func (DiskKaydi) Depola() string { return "disk" }

type BellekKaydi struct{}

func (BellekKaydi) Depola() string { return "bellek" }

type Gecici struct{}

func panikliyorMu(f func()) (p bool) {
	defer func() {
		if recover() != nil {
			p = true
		}
	}()
	f()
	return false
}

func main() {
	degerler := []any{DiskKaydi{}, 42, BellekKaydi{}, "metin", Gecici{}}
	panikSayisi := 0
	for i, d := range degerler {
		panikledi := panikliyorMu(func() {
			_ = d.(Depolayici)
		})
		fmt.Printf("deger#%d dinamik_tip=%T panikledi=%t\n", i, d, panikledi)
		if panikledi {
			panikSayisi++
		}
	}
	fmt.Println("bes degerden panikleyen sayisi:", panikSayisi)
}
```

```
deger#0 dinamik_tip=main.DiskKaydi panikledi=false
deger#1 dinamik_tip=int panikledi=true
deger#2 dinamik_tip=main.BellekKaydi panikledi=false
deger#3 dinamik_tip=string panikledi=true
deger#4 dinamik_tip=main.Gecici panikledi=true
bes degerden panikleyen sayisi: 3
```

Panikleyen sayısı üç, ilk ölçümdeki `dogruSayisi`nin (iki) tam tamamlayıcısı — beş değerin
ikisi karşılıyordu, üçü karşılamıyordu, ve şimdi o üçü tek yanıtlı biçimde panikliyor. İki
ölçüm aynı beş değeri, aynı arayüze karşı, iki ayrı çağrı biçimiyle soruyor ve toplam beşe
tamamlanan iki sayı üretiyor. Bu, iki biçimin aynı bilgiyi taşıdığının bir kanıtı: fark
bilgide değil, başarısızlığın nasıl bildirildiğinde.

## Tip Anahtarının Seçtiği Dal

Tip anahtarı, birden fazla aday arasından tek bir dal seçiyor. `switch v.(type)` yazımı her
`case`i sırayla deniyor ve eşleşen ilk daldan devam ediyor. Go Temelleri kursunun Denetim
Akışı dersinde ölçülen kendiliğinden düşmeme kuralı burada da geçerli: eşleşen dal bir
sonraki `case`e düşmüyor, `fallthrough` yazılmadığı sürece dal kendi başına bitiyor. Aynı
beş değer bu kez dört dallı bir tip anahtarından geçiyor.

```go
// dal-sec.go — tip anahtari bes degeri kendi dallarina dagitiyor
package main

import "fmt"

type Depolayici interface{ Depola() string }

type DiskKaydi struct{}

func (DiskKaydi) Depola() string { return "disk" }

type BellekKaydi struct{}

func (BellekKaydi) Depola() string { return "bellek" }

type Gecici struct{}

func dalSec(v any) string {
	switch t := v.(type) {
	case int:
		return fmt.Sprintf("tam sayi dali: %d", t)
	case string:
		return fmt.Sprintf("dizgi dali: %q", t)
	case DiskKaydi:
		return "DiskKaydi dali"
	case BellekKaydi:
		return "BellekKaydi dali"
	default:
		return "varsayilan dal"
	}
}

func main() {
	degerler := []any{DiskKaydi{}, 42, BellekKaydi{}, "metin", Gecici{}}
	for i, d := range degerler {
		fmt.Printf("deger#%d -> %s\n", i, dalSec(d))
	}
}
```

```
deger#0 -> DiskKaydi dali
deger#1 -> tam sayi dali: 42
deger#2 -> BellekKaydi dali
deger#3 -> dizgi dali: "metin"
deger#4 -> varsayilan dal
```

Beş değerin dördü kendi somut tipine ayrılmış bir dala düşüyor; `Gecici` hiçbir `case`e
uymadığı için `default`e düşüyor. `t := v.(type)` yazımındaki `t`, her dalın içinde o dala
özgü statik tipte bir değişken — `case int` dalında `t` bir `int`, `case string` dalında bir
`string`. Bu, tip anahtarının tip iddiasından farkı: tip iddiası tek bir tipi soruyor, tip
anahtarı aynı sorguyu birden çok adaya karşı tek seferde yürütüp hangisinin eşleştiğini
söylüyor.

Aynı sonucu beş ayrı tip iddiasıyla da elde etmek mümkündü — her aday için bir `if d, tamam
:= v.(X); tamam` satırı yazıp ilk doğru olanı seçmek. Tip anahtarı bunu tek bir yapıda
topluyor ve `t`nin dala özgü statik tipini otomatik olarak sağlıyor; beş ayrı iddiada bu
tipi her dalda elle yeniden yazmak gerekirdi. Kazanılan şey bir yeni yetenek değil, aynı
sorgunun tek bir yerde toplanması.

## Sınırlayıcı Ölçüm: Seçilen Dal Yazılış Sırasına Bağlı

Tip anahtarı yalnız somut tipleri değil, arayüzleri de dal olarak kabul ediyor. Bir değer
hem bir somut tip dalına hem bir arayüz dalına uyabiliyorsa, hangisinin seçileceği dalların
**yazılış sırasına** bağlı — ilk eşleşen dal kazanıyor.

Önceki bölümdeki dört dal (`int`, `string`, `DiskKaydi`, `BellekKaydi`) birbirini dışlıyordu:
tek bir değer bu dallardan yalnız birine uyabiliyordu. Ama bir somut tip ile o tipin
karşıladığı bir arayüz birbirini dışlamıyor — `DiskKaydi` hem `DiskKaydi`nin kendisi hem
`Depolayici` demek. İki `case` aynı değeri talep ettiğinde tip anahtarı bir çakışma hatası
vermiyor, sessizce ilk yazılanı seçiyor.

```go
// sira-bagimliligi.go — ayni deger, dallarin sirasina gore iki ayri sonuc veriyor
package main

import "fmt"

type Depolayici interface{ Depola() string }

type DiskKaydi struct{}

func (DiskKaydi) Depola() string { return "disk" }

func siniflaSomutOnce(v any) string {
	switch v.(type) {
	case DiskKaydi:
		return "somut: DiskKaydi"
	case Depolayici:
		return "arayuz: Depolayici"
	default:
		return "bilinmeyen"
	}
}

func siniflaArayuzOnce(v any) string {
	switch v.(type) {
	case Depolayici:
		return "arayuz: Depolayici"
	case DiskKaydi:
		return "somut: DiskKaydi"
	default:
		return "bilinmeyen"
	}
}

func main() {
	v := DiskKaydi{}
	fmt.Println("somut dal once yazilirsa  :", siniflaSomutOnce(v))
	fmt.Println("arayuz dali once yazilirsa:", siniflaArayuzOnce(v))
}
```

```
somut dal once yazilirsa  : somut: DiskKaydi
arayuz dali once yazilirsa: arayuz: Depolayici
```

`DiskKaydi{}` iki dala da uyuyor: kendi somut tipine ve `Depolayici`ye, çünkü `Depola`
yöntemini karşılıyor. `siniflaSomutOnce` `DiskKaydi` dalını önce yazdığı için o dalı
seçiyor; `siniflaArayuzOnce` aynı değeri, yalnız dalların sırası tersine çevrildiği için,
`Depolayici` dalına düşürüyor. Kaynak metin iki işlevde de aynı iki `case`i taşıyor,
yalnız sırası değişmiş; sonuç bambaşka. Bu, önceki dersteki küçük arayüz ölçümüyle aynı
gerçeğe farklı bir açıdan bakıyor: bir değer birden çok arayüzü aynı anda karşılayabiliyor,
ve tip anahtarı bu çokluğu ilk yazılan dalı seçerek çözüyor.

**AR9.** Bu sıra bağımlılığı yalnız somut tip ile arayüz dalı arasında değil, iki ayrı
arayüz dalı arasında da geçerli — bir değer iki arayüzü birden karşılıyorsa, hangi arayüz
dalının önce yazıldığı yine kazanıyor. Ölçüm burada tek bir çifti (somut tip, arayüz)
sınıyor çünkü bu, kaynakta en sık karşılaşılan biçim; ilke ikiden fazla dal için de aynı
kalıyor.

Bunun sonucu, normal bir `switch`teki alışılmış sezgiyle çelişiyor: sıradan bir `switch`te
dalların sırası genellikle yalnız okunabilirliği etkiler, sonucu değiştirmez, çünkü her dal
birbirini dışlayan ayrı bir değeri karşılaştırır. Tip anahtarında dallar birbirini
dışlamayabilir — bir değer aynı anda birden fazla dala uyabilir — ve bu durumda sıra artık
salt bir okunabilirlik tercihi değil, hangi dalın çalışacağını belirleyen bir karardır.
Ölçümün gösterdiği şey tam olarak bu: iki işlev aynı iki `case`i taşıyor, aynı değeri
alıyor, ve yalnız bir satırın yerinin değişmesiyle iki ayrı yanıt üretiyor.

## Özet

- Tip iddiasının iki yanıtlı biçimi (`v, tamam := deger.(Tip)`) başarısızlığı bir mantıksal
  değere çeviriyor; beş değerden ikisi `Depolayici`yi karşılıyor, üçü karşılamıyor.
- Tek yanıtlı biçim (`v := deger.(Tip)`) başarısız olduğunda panikliyor; panik yalnız
  `recover` ile yakalanıp `panik=true`/`panik=false` olarak okunuyor.
- Tip anahtarı aynı sorguyu birden çok adaya karşı tek seferde yürütüyor ve eşleşen ilk
  daldan devam ediyor, bir sonraki dala düşmüyor.
- Bir değer hem bir somut tip dalına hem bir arayüz dalına uyabiliyor; seçilen dal kaynağın
  yazılış sırasına bağlı, değerin kendisine değil.
- İki yanıtlı biçimin panik üretmemesi ile tek yanıtlı biçimin panik sayısının (üç) iki
  yanıtlı biçimin `false` sayısını (üç) tam karşılaması, iki çağrı biçiminin aynı bilgiyi
  taşıdığını, yalnız başarısızlığı farklı bildirdiğini gösteriyor.
- Tip iddiası başarılı olduğunda geri dönen değer gerçekten çağrılabilir; önceki dersteki
  "doğrudan çağrılamaz" bedeli, başarılı bir iddiadan sonra geri ödeniyor.

## Sonraki Adım

Bu derste `Depolayici` tek bir yöntem istiyordu ve tek bir sözleşme kuruyordu. Ama bir tip
birden çok sözleşmeyi aynı anda karşılamak zorunda kaldığında — hem depolayabilmeli hem
kapatılabilmeli — bu iki sözleşmeyi kaynakta birleştirmenin bir yolu gerekiyor. Sınırlayıcı
ölçümdeki `Depolayici` dalı da böyle bir birleşmenin habercisiydi: `DiskKaydi` yalnız
`Depola` yazdı ama başka sözleşmeleri de karşılayabilirdi. Sıradaki ders bu birleşmeyi
ölçüyor: gömülü arayüzler bir sözleşmeyi kaynakta nasıl kuruyor, ve bu birleşme
gerçekleştirime hiç yeni yöntem eklemeden nasıl oluyor?
