---
title: 'Arayüz Kavramı'
source: 'https://academia.sh/tr/kurslar/go-tip-sistemi/arayuz-kavrami'
course: 'Arayüzler, Hatalar ve Genellikler'
language: tr
updated: '2026-08-23T14:25:02+00:00'
license: 'CC BY-SA 4.0'
---

# Arayüz Kavramı

On altı bağın 4'ü bildirimde, 4'ü kullanım yerinde, 8'i değerin içinde kuruluyor: kursun bağlayıcı dağılımı burada üretiliyor. Aynı tip dört arayüzü karşılıyor ve kaynağında sıfır atıf var; küçük arayüz ilkesi burada bir öğüt değil, yöntem sayısı arttıkça karşılayan tip sayısının düşmesiyle ölçülen bir gözlem. Sınırlayıcı ölçüm: derleme zamanı uyum kanıtı aynı bağı bildirime taşıyor, kanıt yokken derleyici sessiz kalıyor.

Go Temelleri kursu bir adın görünürlüğünü, bir bağımlılığın sürümünü ve bir biçim kuralının
uygulanmasını kimin belirlediğini sorarak kapandı — üçünün de yanıtı dilin kendisiydi: dışa
aktarma bir harfin büyüklüğüne, sürüm seçimi modül dosyasının yazdığı en düşük isteğe, biçim
kuralı biçimlendiricinin kendisine bağlıydı. Bu ders aynı soruyu bir adım içeri taşıyor. Bir
tip bir arayüzü karşıladığında, bunu söyleyen tek bir satır yoktur — ne arayüzün tanımında, ne
tipin kendi kaynağında. Derleyici bu bağı biliyor, ama kaynağı okuyan biri onu göremiyor.
Öyleyse bu bağ nerede kuruluyor?

Bu kurs bu soruyu on altı kez soruyor — arayüzlerde, hata değerlerinde, genelliklerde — ve her
seferinde yanıtı üç yerden birine yazıyor: bağ kaynakta açıkça mı yazılı (**bildirim**),
derleyici onu bir değerin kullanıldığı yerde mi kuruyor (**kullanım yeri**), yoksa bağ çalışma
zamanında değerin kendisinde mi taşınıyor (**değer**). Bu ders bu üç yeri ilk kez sayıyor ve
kursun geri kalanının atıf yapacağı sayıyı üretiyor.

## Bağ Nerede Kuruluyor

Bir arayüz bir yöntem kümesi tanımlar ve kendi başına hiçbir şey yapmaz — ne bir alan taşır ne
bir davranış üretir. Bir tip, o yöntem kümesinin tamamını kendi yöntemleriyle karşılıyorsa
arayüzü **karşılar**. Karşılamanın **örtük** olması, tipin kaynağında bunu bildiren hiçbir
sözcüğün geçmemesi demek. Bir tip, kendi yazarının hiç duymadığı bir arayüzü bile
karşılayabilir; tek koşul yöntem imzalarının eşleşmesidir.

Karşılamanın kendisi hiçbir zaman kaynakta yazılı değildir. Ama bu karşılamayı **doğrulayan
bir kanıt** kaynağa eklenebilir — o zaman bağ bildirime taşınır. Bu ayrım dersin son
bölümünün konusu. Şimdilik üç sınıfın sözlü tanımı yeterli: hangi bağın kaynakta açıkça
durduğunu, hangisinin derleyici tarafından kullanım anında kurulduğunu, hangisinin çalışma
zamanında değerle birlikte taşındığını ölçüm **saydırıyor**; bu bilgiyi biz baştan biliyoruz.

## Çerçeve: Bağı Sınıflayan Bir Gözlemci

Ölçüm, her bağı tek bir soruyla sınıflayan küçük bir gözlemciden geçiyor. Üç paket düzeyi
sayaç (`bildirim`, `kullanimYeri`, `deger`) her gözlemi bir sınıfa yazıyor; `gozle` tek giriş
noktası, `ozet` toplamı basıyor.

```go
// bag.go — bir bag nerede kuruluyor: bildirimde mi, kullanim yerinde mi, degerin icinde mi
package main

import "fmt"

var bildirim, kullanimYeri, deger int

func gozle(ad, yer, kanit string) {
	switch yer {
	case "bildirim":
		bildirim++
	case "kullanim":
		kullanimYeri++
	default:
		deger++
	}
	fmt.Printf("%-40s %-10s %s\n", ad, yer, kanit)
}

func ozet() {
	fmt.Printf("bag: %d bildirim, %d kullanim yeri, %d deger\n", bildirim, kullanimYeri, deger)
}
```

**AR1.** `gozle` her satırı üç parçayla alıyor: bir ad, bir sınıf, bir kanıt. Kanıt sütunu
iddiayı doğrulayan gerçek değeri taşıyor — hangi satırın hangi sınıfa girdiği elde önceden
biliniyor, çerçeve bu kararı üretmiyor, yalnız **saydırıyor**. Sayaçların paket düzeyinde
tutulması, `ozet` çağrıldığında toplamın gözlemlerle her zaman tutarlı kalmasını sağlıyor.

## On Altı Bağ

Bu çerçeve tek bir pakette on altı bağı sırayla soruyor. Ölçüm arayüz karşılamasıyla açılıyor,
gömme ve derleme zamanı kanıtla sürüyor, boş arayüze konan bir değerin dinamik tipiyle,
tip iddiasının ve tip anahtarının değere sorduğu soruyla, tüketici tarafında tanımlanan bir
arayüzle, hata değerinin örtük karşılanmasıyla, nöbetçi bir hatanın kimliğiyle, sarmalanan bir
hatanın taşıdığı bağlamla, ve son olarak genel bir fonksiyonun çıkardığı tip parametresiyle,
bir tip kısıtının bildirimiyle, genel bir yapının örneklenmesiyle kapanıyor.

```go
// olcum.go — on alti bag, uc yere bolunur
package main

import (
	"errors"
	"fmt"
)

type Yazar interface{ Yaz(m string) string }
type Kapatan interface{ Kapat() error }

// Kisa, tuketici tarafinda tanimlanan bir arayuz: ureten tip onu hic anmiyor.
type Kisa interface{ Yaz(m string) string }

// Gomulu, iki sozlesmeyi bildirimde birlestiriyor.
type Gomulu interface {
	Yazar
	Kapatan
}

type Dosya struct{ Ad string }

func (d Dosya) Yaz(m string) string { return d.Ad + ":" + m }
func (d Dosya) Kapat() error        { return nil }

// Derleme zamani uyum kaniti: yazan taraf bunu bildirime koydu.
var _ Gomulu = Dosya{}

type Kayit struct{ Sayi int }

func (k *Kayit) Hata() string { return "kayit" }

var ErrYok = errors.New("bulunamadi")

type AlanHatasi struct{ Alan string }

func (a *AlanHatasi) Error() string { return "alan gecersiz: " + a.Alan }

func ara(bulundu bool) error {
	if !bulundu {
		return fmt.Errorf("arama basarisiz: %w", ErrYok)
	}
	return nil
}

func dogrula() error {
	return fmt.Errorf("kayit dogrulanamadi: %w", &AlanHatasi{Alan: "ad"})
}

func ilki[T any](d []T) (T, bool) {
	var sifir T
	if len(d) == 0 {
		return sifir, false
	}
	return d[0], true
}

type Sayisal interface{ ~int | ~float64 }

func topla[T Sayisal](d []T) T {
	var t T
	for _, e := range d {
		t += e
	}
	return t
}

type Yigin[T any] struct{ ogeler []T }

func (y *Yigin[T]) Ekle(o T) { y.ogeler = append(y.ogeler, o) }
func (y *Yigin[T]) Tip() string {
	var sifir T
	return fmt.Sprintf("%T", sifir)
}

func main() {
	fmt.Println("-- bag nerede kuruluyor --")

	var y Yazar = Dosya{Ad: "not"}
	gozle("tipin arayuzu karsilamasi", "kullanim", "kaynakta hicbir yerde yazili degil")
	gozle("derleme zamani uyum kaniti", "bildirim", "var _ Gomulu = Dosya{}")
	gozle("arayuz gomme", "bildirim", "Gomulu = Yazar + Kapatan")

	gozle("arayuz degerinin dinamik tipi", "deger", fmt.Sprintf("%T", y))

	d, tamam := y.(Kapatan)
	gozle("tip iddiasinin yaniti", "deger", fmt.Sprint(tamam, " ", d != nil))

	var tur string
	switch y.(type) {
	case Dosya:
		tur = "Dosya"
	default:
		tur = "bilinmeyen"
	}
	gozle("tip anahtarinin sectigi dal", "deger", tur)

	var _ Kisa = Dosya{}
	gozle("arayuzun tuketici tarafinda tanimlanmasi", "kullanim",
		"Dosya dort arayuzu karsiliyor, kaynaginda sifir atif var")

	var bosArayuz any = y
	gozle("bos arayuze konan degerin tipi", "deger", fmt.Sprintf("%T", bosArayuz))

	var k *Kayit
	var h any = k
	gozle("nil isaretci tasiyan arayuz", "deger", fmt.Sprint("isaretci nil=", k == nil, " arayuz nil=", h == nil))

	var hata error = &AlanHatasi{Alan: "ad"}
	gozle("hata arayuzunun karsilanmasi", "kullanim", fmt.Sprintf("%T", hata))

	sarmali := ara(false)
	gozle("nobetci hatanin kimligi", "deger", fmt.Sprint(errors.Is(sarmali, ErrYok)))
	gozle("sarmalamanin tasidigi metin", "deger", sarmali.Error())

	var hedef *AlanHatasi
	gozle("sarmali zincirden tip cikarma", "deger", fmt.Sprint(errors.As(dogrula(), &hedef), " ", hedef.Alan))

	ilk, varMi := ilki([]string{"a", "b"})
	gozle("genel fonksiyonun tip cikarimi", "kullanim", fmt.Sprint(ilk, " ", varMi))

	gozle("tip kisitinin bildirimi", "bildirim", fmt.Sprint("Sayisal ile toplam=", topla([]int{1, 2, 3})))

	var yigin Yigin[float64]
	yigin.Ekle(1.5)
	gozle("genel tipin orneklenmesi", "bildirim", "Yigin[float64] -> "+yigin.Tip())

	ozet()
}
```

```
-- bag nerede kuruluyor --
tipin arayuzu karsilamasi                kullanim   kaynakta hicbir yerde yazili degil
derleme zamani uyum kaniti               bildirim   var _ Gomulu = Dosya{}
arayuz gomme                             bildirim   Gomulu = Yazar + Kapatan
arayuz degerinin dinamik tipi            deger      main.Dosya
tip iddiasinin yaniti                    deger      true true
tip anahtarinin sectigi dal              deger      Dosya
arayuzun tuketici tarafinda tanimlanmasi kullanim   Dosya dort arayuzu karsiliyor, kaynaginda sifir atif var
bos arayuze konan degerin tipi           deger      main.Dosya
nil isaretci tasiyan arayuz              deger      isaretci nil=true arayuz nil=false
hata arayuzunun karsilanmasi             kullanim   *main.AlanHatasi
nobetci hatanin kimligi                  deger      true
sarmalamanin tasidigi metin              deger      arama basarisiz: bulunamadi
sarmali zincirden tip cikarma            deger      true ad
genel fonksiyonun tip cikarimi           kullanim   a true
tip kisitinin bildirimi                  bildirim   Sayisal ile toplam=6
genel tipin orneklenmesi                 bildirim   Yigin[float64] -> float64
bag: 4 bildirim, 4 kullanim yeri, 8 deger
```

On altı bağın **4'ü bildirimde, 4'ü kullanım yerinde, 8'i değerin içinde** kuruluyor. Bu
dağılım kursun geri kalanı için bağlayıcı; sonraki dersler kendi diliminin satırlarını basıp
bu tabloya tek cümleyle atıf yapacak. Sekizinin değerde kurulması Go'nun arayüz değerinin bir
**çift** olmasından geliyor — içinde hem somut tip hem değer duruyor; tip iddiası, tip
anahtarı, nöbetçi hata karşılaştırması ve sarmalı zincirden tip çıkarma dördü de aynı çiftin
okunması. Bu derste asıl konu ilk iki satır ve yedinci satır: arayüz karşılamasının kendisi ve
onun tüketici tarafında tanımlanması.

## Örtük Gerçekleştirim: Sıfır Atıflı Dört Arayüz

`Dosya` tipinin kaynağı iki satırdan ibaret: bir alan, iki yöntem (`Yaz`, `Kapat`). Bu iki
satır dört ayrı arayüzü karşılıyor — `Yazar` (`Yaz` yöntemini istiyor), `Kapatan` (`Kapat`
yöntemini istiyor), `Gomulu` (ikisini birden gömerek istiyor) ve `Kisa` (yalnız `Yaz`
istiyor, `Yazar`la aynı imzayı taşıyan ayrı bir tanım). `Dosya`nın kendi kaynağında bu dört
arayüzün adı **hiç geçmiyor** — ne `type Dosya struct` satırında, ne `Yaz` ve `Kapat`
yöntemlerinin gövdesinde. Kaynağa sıfır atıf var, karşılama sayısı dört.

Bu, örtük gerçekleştirimin somut sonucu: bir tip, kendi yazarının hiç görmediği bir arayüzü
bile karşılayabiliyor, çünkü karşılamanın koşulu yalnızca yöntem imzalarının eşleşmesi. `Kisa`
arayüzü `olcum.go` içinde `Yazar`dan **sonra** tanımlandı ve `Dosya` ondan habersiz yazıldı;
buna rağmen `var _ Kisa = Dosya{}` satırı derleniyor. Tablodaki yedinci satır bunu bir sayıya
indiriyor: dört arayüz, sıfır atıf. Bu gözlem beşinci dersin konusu olan tüketici tarafında
tanımlamanın ilk görünümü — orada aynı fikir bir tasarım kararına dönüşecek.

## Küçük Arayüz İlkesi: Öğüt Değil Ölçüm

Bir arayüzün yöntem sayısı arttıkça, onu karşılayan tip sayısının düşmesi beklenir — daha
çok yöntem istemek daha sıkı bir koşul demek. Bu, Tasarım İlkeleri kursunun arayüz ayrımı
ilkesinin dayandığı sezgi; burada bir öğüt olarak değil, sayılabilir bir ilişki olarak
ölçülüyor.

```go
// kucuk-arayuz.go — arayuzun yontem sayisi arttikca onu karsilayan tip sayisi azaliyor mu
package main

import "fmt"

type BirYontemli interface{ Oku() string }
type IkiYontemli interface {
	Oku() string
	Yaz(m string)
}
type UcYontemli interface {
	Oku() string
	Yaz(m string)
	Kapat() error
}

type SadeceOkuyan struct{}

func (SadeceOkuyan) Oku() string { return "oku" }

type OkuyupYazan struct{}

func (OkuyupYazan) Oku() string  { return "oku" }
func (OkuyupYazan) Yaz(m string) {}

type OkuyupYazipKapatan struct{}

func (OkuyupYazipKapatan) Oku() string  { return "oku" }
func (OkuyupYazipKapatan) Yaz(m string) {}
func (OkuyupYazipKapatan) Kapat() error { return nil }

type SadeceYazan struct{}

func (SadeceYazan) Yaz(m string) {}

func main() {
	tipler := []any{SadeceOkuyan{}, OkuyupYazan{}, OkuyupYazipKapatan{}, SadeceYazan{}}

	birSayisi, ikiSayisi, ucSayisi := 0, 0, 0
	for _, t := range tipler {
		if _, tamam := t.(BirYontemli); tamam {
			birSayisi++
		}
		if _, tamam := t.(IkiYontemli); tamam {
			ikiSayisi++
		}
		if _, tamam := t.(UcYontemli); tamam {
			ucSayisi++
		}
	}
	fmt.Println("bir yontemli arayuzu karsilayan tip sayisi:", birSayisi)
	fmt.Println("iki yontemli arayuzu karsilayan tip sayisi:", ikiSayisi)
	fmt.Println("uc yontemli arayuzu karsilayan tip sayisi :", ucSayisi)
}
```

```
bir yontemli arayuzu karsilayan tip sayisi: 3
iki yontemli arayuzu karsilayan tip sayisi: 2
uc yontemli arayuzu karsilayan tip sayisi : 1
```

**AR2.** Dört tip bilinçli olarak kuruldu: üçü `Oku`yu artan yöntem kümeleriyle taşıyor,
dördüncüsü (`SadeceYazan`) hiç `Oku` taşımıyor ve üç arayüzün de dışında kalıyor. Bu son tip
olmasaydı düşüş yine görülürdü ama "arayüzü hiç karşılamayan bir tip de var" gözlemi
kaybolurdu — ölçüm bu yüzden dördü birlikte tutuyor.

Dört tip, üç arayüz karşısında sınandığında sayı **3, 2, 1** olarak düşüyor: yöntem kümesi
bir yöntemden üçe çıktıkça, aynı dört tipten onu karşılayabilenlerin sayısı azalıyor. Bu bağ
tabloda görülen "kullanım yeri" sınıfının aynısı — her sayım, bir tip iddiasının çağrıldığı
satırda kuruluyor, tipin ya da arayüzün kendi tanımında değil. Küçük arayüz, az yöntem isteyen
arayüz demek; az yöntem isteyen arayüz, çoğu tipin karşıladığı arayüz demek. Bu bir tasarım
öğüdü değil, yukarıdaki sayımın doğrudan sonucu.

## Sınırlayıcı Ölçüm: Uyum Kaynakta da Yazılabilir

On altı bağın ilk satırı "kullanım yeri" diyordu ve kanıtı dolaylıydı: karşılamanın kaynakta
yazılı olmadığını gösterdi, kurulduğu yeri değil. Bu bölüm doğrudan kanıtı veriyor: uyumu
kasten bozup derleyicinin nerede durduğunu gösteriyor. Araç, Go Temelleri kursunun `eksik.go`
çerçevesindeki `derlenirMi` — bir kaynak parçasını geçici bir pakete yazıp derleyiciyi çağırıyor
ve yalnız geçip geçmediğini okuyor.

```go
// arac.go — bir kaynak parcasinin derlenip derlenmedigini programin icinden sinar
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
}
```

Bu iki kaynak parçası aynı yarım gerçekleştirimi taşıyor — bir tip, iki yöntemli bir arayüzün
yalnız birini yazıyor. Fark tek satır: ikincisinde tipin hemen ardından bir uyum kanıtı var.

```go
// uyum-kaniti.go — kanit yokken derleyici sessiz kaliyor, kanit varsa bildirimde duruyor
package main

import "fmt"

func main() {
	kaynakA := `package sinama

type TamArayuz interface {
	Birinci() string
	Ikinci() string
}

type YarimGerceklestirim struct{}

func (y YarimGerceklestirim) Birinci() string { return "birinci" }
`
	kaynakB := kaynakA + `
var _ TamArayuz = YarimGerceklestirim{}
`
	fmt.Println("kanitsiz, hic kullanilmadan   :", derlenirMi(kaynakA))
	fmt.Println("kanitla, tanimin hemen ardinda:", derlenirMi(kaynakB))
}
```

```
kanitsiz, hic kullanilmadan   : true
kanitla, tanimin hemen ardinda: false
```

`YarimGerceklestirim` iki kaynakta da aynı — `Ikinci` yöntemi eksik. Birinci kaynakta bu tip
hiçbir yerde `TamArayuz` olarak kullanılmıyor; derleyici sessiz kalıyor ve eksik yöntem hiçbir
uyarı üretmiyor. İkinci kaynakta tek eklenen satır, tipin tanımının hemen ardına konan bir
uyum kanıtı; aynı eksiklik şimdi derlemeyi durduruyor. Bağ ikinci kaynakta **bildirime**
taşınmış oldu — kanıt satırı, karşılamanın kendisini değil, karşılamanın **doğrulamasını**
kaynağa yazıyor, ve bu doğrulama bozulduğunda derleme orada duruyor.

**AR3.** Bu ölçümün bir kör noktası var: `derlenirMi` yalnız `cmd.Run()`ın çıkış durumunu
okuyor, hata metnini hiç okumuyor. Birinci kaynağın gerçekten **başka** bir nedenle değil,
yalnız eksik yöntem yüzünden derlendiğinden emin olmak elle kuruldu — kaynak, `Ikinci`
dışında hiçbir sorun taşımayacak şekilde yazıldı. Kursun derleyici çağıran her ölçümünde aynı
disiplin sürüyor.

Uyum kanıtı olmadan bırakılan bir tip, hiç kullanılmadığı sürece eksikliğini asla göstermez.
Bu, "kullanım yerinde kuruluyor" demenin gerçek maliyeti: bağ yalnız kullanıldığı anda
sınanıyor, kullanılmazsa hiç sınanmıyor. Bir kanıt satırı bu riski, tipin tanımının yanına
taşıyarak kapatıyor.

## Özet

- Bir tipin bir arayüzü karşılaması örtüktür: bunu bildiren hiçbir sözcük kaynakta geçmez;
  tek koşul yöntem imzalarının eşleşmesidir.
- On altı bağın **4'ü bildirimde, 4'ü kullanım yerinde, 8'i değerin içinde** kuruluyor —
  kursun bağlayıcı dağılımı bu derste üretildi.
- `Dosya` tipi dört arayüzü (`Yazar`, `Kapatan`, `Gomulu`, `Kisa`) karşılıyor ve kendi
  kaynağında bu dördüne sıfır atıf var.
- Küçük arayüz ilkesi bir öğüt değil ölçüm: yöntem sayısı bir–iki–üçe çıktıkça, aynı dört
  tipten onu karşılayabilenlerin sayısı üç–iki–bire düşüyor.
- Derleme zamanı uyum kanıtı (`var _ Arayuz = Tip{}`) bağı bildirime taşıyor; kanıt yokken
  eksik bir gerçekleştirim, kullanılmadığı sürece hiç görünmüyor.

## Sonraki Adım

Bu derste arayüz değerinin dinamik tipi bir kez göründü — `%T` ile okunan `main.Dosya` — ama
üzerinde durulmadı. Sıradaki ders tam olarak bu satırı büyütüyor: hiçbir yöntem istemeyen boş
arayüz, hangi tip konursa konsun onu kabul ediyor, ama konan tipin bilgisi kaybolmuyor. O
bilgi nereye gidiyor, ve `%T` onu nasıl geri okuyor?
