---
title: 'Komut Satırı Uygulamaları'
source: 'https://academia.sh/tr/kurslar/go-uygulamalar/komut-satiri-uygulamalari'
course: 'Standart Kütüphane ve Ağ Uygulamaları'
language: tr
updated: '2026-08-23T16:55:13+00:00'
license: 'CC BY-SA 4.0'
---

# Komut Satırı Uygulamaları

Kursun ve konunun son dersi. Bir bayrak ayrıştırıcısına elle verilen dizgi dizisinden tam sayı, mantıksal, süre ve dizgi tiplerinin geri kurulması; tanınmayan bir bayrağın ayrıştırmayı durdurduğu; alt komut yapısında her alt komutun kendi bayrak kümesini taşıdığı koşturularak ölçülüyor. Sınırlayıcı ölçüm: ayrıştırıcı beklenen tipi geri kurur, değerin anlamını değil — negatif bir adet hiçbir hata üretmeden geçiyor. Kurs kapanışında on iki dersin ölçtüğü sınır geçişleri tek bir tabloda toparlanıyor.

Önceki ders bir veritabanı satırının sürücünün dar tip kümesinden hedef değişkenin kendi
`Scan` yöntemiyle geri kurulduğunu gösterdi ve konunun beş dersini kapattı: dosya ve
arabellek, ikili dosyaya gömülen bir kaynak, metne dönen bir zaman değeri, alan adlarını
taşıyan bir günlük kaydı, bir veritabanı satırı — beşinde de sınırı geçen değer kendi başına
yeterli değildi, geri kurmayı sağlayan şey her seferinde karşı tarafın elindeki bir tarifti.
Bu ders aynı soruyu programın kendi **girişine** taşıyor: bir komut satırı bayrağı da, tıpkı
bir günlük satırı ya da bir veritabanı sütunu gibi, programa dizgi olarak giriyor. Kabuk
Programlama kursu (M03/K02) bu argümanların kabuk tarafında nasıl kurulduğunu ve metnin nasıl
işlendiğini zaten kurdu; bu ders onu tekrar etmiyor, yalnız argümanın programın eline
geçtiği noktadan devam ediyor — dizgi elde tutulduğunda, tipi kim, hangi tarifle geri
kuruyor?

Yanıt bu kursun standart kitaplığındaki **komut satırı bayrağı** ayrıştırıcısında duruyor.
Bu ders boyunca yalnız kısaca "bayrak" deniyor, ama kastedilen hep bu: bir çağrının önüne
`-` ile eklenen, dizgi olarak gelen bir komut satırı seçeneği. Ayrıştırıcı bir
dizgi dizisini alıp, kaynakta önceden bildirilmiş bayrak adlarına göre, her bayrağın beklediği
tipte bir değer üretiyor — tarif burada da karşı tarafın elinde, ama bu kez karşı taraf ağın
ötesi ya da bir sürücü değil, kaynağın kendisinde `kume.Int`, `kume.Bool`, `kume.String` gibi
çağrılarla yazılmış bildirimler. Bu ders üç şeyi ölçüyor: ayrıştırıcının dört tipi (tam sayı,
mantıksal, süre, dizgi) dizgiden nasıl geri kurduğunu, tanınmayan bir bayrağın ayrıştırmayı
nerede durdurduğunu, ve alt komut yapısının her alt komuta kendi bayrak kümesini nasıl
verdiğini. **Gerçek argüman listesi (`os.Args`) hiçbir yerde okunmuyor** — bayrak kümesine
her seferinde elle kurulmuş bir dizgi dizisi veriliyor, tıpkı önceki derste kukla sürücüye
elle kurulmuş bir satır verildiği gibi. Konunun son ve kursun kapanış dersi olarak bu ders
ayrıca on iki dersin ölçtüğü sınır geçişlerini tek bir tabloda topluyor.

## Bayrak Ayrıştırıcının Dizgiden Geri Kurduğu Dört Tip

Standart kitaplığın bayrak paketi, tek bir küresel bayrak kümesi (`flag.CommandLine`) yanında,
kendi bayrak kümesini kurmayı da destekliyor: `flag.NewFlagSet` bağımsız bir küme döndürüyor,
ve bu küme `os.Args`e hiç dokunmadan, kendisine verilen herhangi bir dizgi dilimini
ayrıştırabiliyor. Bu ders boyunca yalnız bu bağımsız kümeler kullanılıyor — bir kısıt değil,
gerçek kaynak yasağının doğal bir sonucu: `os.Args` koşumun kendi ortamına bağlı bir kaynak,
bu yüzden ölçüm ona hiç dokunmuyor.

**SS20.** — Dört bayrak (tam sayı, mantıksal, süre, dizgi) bir bayrak kümesine bildiriliyor;
elle kurulmuş bir dizgi dizisi ayrıştırılıp her bayrağın geri kurduğu değerin tipi `%T` ile
okunuyor.

```go
// tipler.go — bayrak ayristiricinin dizgiden geri kurdugu dort tip
package main

import (
	"flag"
	"fmt"
	"io"
)

func main() {
	kume := flag.NewFlagSet("olcum", flag.ContinueOnError)
	kume.SetOutput(io.Discard)

	adet := kume.Int("adet", 0, "adet")
	kalici := kume.Bool("kalici", false, "kalici mi")
	bekleme := kume.Duration("bekleme", 0, "bekleme suresi")
	ad := kume.String("ad", "", "ad")

	girdi := []string{"-adet", "12", "-kalici", "-bekleme", "1h30m", "-ad", "vida"}
	kume.Parse(girdi)

	fmt.Println("-- dizgiden geri kurulan dort tip --")
	fmt.Printf("%-8s kaynak=%-7q deger=%-8v tip=%T\n", "adet", "12", *adet, *adet)
	fmt.Printf("%-8s kaynak=%-7q deger=%-8v tip=%T\n", "kalici", "(var)", *kalici, *kalici)
	fmt.Printf("%-8s kaynak=%-7q deger=%-8v tip=%T\n", "bekleme", "1h30m", *bekleme, *bekleme)
	fmt.Printf("%-8s kaynak=%-7q deger=%-8v tip=%T\n", "ad", "vida", *ad, *ad)
}
```

```
-- dizgiden geri kurulan dort tip --
adet     kaynak="12"    deger=12       tip=int
kalici   kaynak="(var)" deger=true     tip=bool
bekleme  kaynak="1h30m" deger=1h30m0s  tip=time.Duration
ad       kaynak="vida"  deger=vida     tip=string
```

Dört bayrağın dördü de kaynakta **dizgi olarak** duruyor — `girdi` dilimindeki her eleman bir
`string`, başka bir şey değil. `kume.Int`in döndürdüğü `*int` işaretçisinin arkasındaki değer
`"12"` dizgisinden ayrıştırılan bir tam sayı; `kume.Bool` bir bayrağın **varlığını** (değer
yazılmadan yalnız adının geçmesini) `true` olarak okuyor; `kume.Duration` `"1h30m"` dizgisini
`time.Duration` tipinde, saat ve dakikaya ayrıştırılmış bir değere çeviriyor; `kume.String` ise
hiçbir dönüşüm yapmadan aynı dizgiyi geri veriyor. Dördü de kendi tipini `%T` ile doğruluyor —
ayrıştırıcı burada tam olarak Veritabanı Erişimi dersindeki `Scan` yönteminin yaptığı şeyi
yapıyor: kaynakta tip bilgisi taşımayan bir veriyi (orada sürücünün dar tip kümesi, burada çıplak
dizgi), hedefte önceden bildirilmiş bir tarifle bir Go tipine geri kuruyor.

Bu geri kurma otomatik değil, **bildirime bağlı**. `kume.Int("adet", 0, "adet")` çağrısı
ayrıştırıcıya "`adet` adlı bayrak bir tam sayı taşıyacak" diye önceden söylüyor; bu bildirim
olmasaydı ayrıştırıcının `"12"` dizgisini bir tam sayı mı, bir dizgi mi okuyacağını bilecek
hiçbir yolu yoktu. Tıpkı yapı etiketinin bir JSON alanının adını taşıması gibi, burada da
tarif kaynağın kendisinde değil, ayrıştırıcıyı kuran kodun kendisinde duruyor.

## Tanınmayan Bayrağın Ne Yaptığı

Bir bayrak kümesi yalnızca kendisine önceden bildirilen adları tanıyor. Dizgi dizisinde
bildirilmemiş bir ad geçtiğinde ayrıştırıcı bunu sessizce yok saymıyor — ayrıştırmayı orada
**durduruyor** ve bir hata döndürüyor.

**SS21.** — Bilinen bir bayraktan sonra tanınmayan bir bayrak, ondan sonra da bilinen ikinci
bir bayrak geçiyor; ayrıştırma tanınmayan bayrakta durduğu için ikinci bilinen bayrağın hiç
okunmadığı ölçülüyor.

```go
// bilinmeyen.go — taninmayan bir bayrak ayristirmayi durduruyor, sonrasi hic okunmuyor
package main

import (
	"flag"
	"fmt"
	"io"
)

func main() {
	kume := flag.NewFlagSet("olcum", flag.ContinueOnError)
	kume.SetOutput(io.Discard)

	adet := kume.Int("adet", 0, "adet")
	ad := kume.String("ad", "baslangic", "ad")

	girdi := []string{"-adet", "5", "-bilinmeyen", "x", "-ad", "vida"}
	hata := kume.Parse(girdi)

	fmt.Println("-- taninmayan bayragin ne yaptigi --")
	fmt.Println("ayristirma hata dondurdu mu:", hata != nil)
	fmt.Println("adet (taninmayandan once okundu):", *adet)
	fmt.Println("ad (taninmayandan sonra, hic okunmadi):", *ad)
}
```

```
-- taninmayan bayragin ne yaptigi --
ayristirma hata dondurdu mu: true
adet (taninmayandan once okundu): 5
ad (taninmayandan sonra, hic okunmadi): baslangic
```

`adet` bayrağı `-bilinmeyen`den **önce** geçtiği için ayrıştırıcı onu sorunsuz okuyup `5`e
atıyor. `-bilinmeyen` bayrağına geldiğinde ise `kume`de bu adla bildirilmiş hiçbir bayrak
olmadığını görüyor ve `Parse` hemen bir hatayla dönüyor — dizgi dizisinin geri kalanı
(`-ad vida`) hiç işlenmiyor, `ad` kendi varsayılan değerinde (`"baslangic"`) kalıyor. Bu,
Go'nun kendi dağıtımının çoğu komutunda görülen davranış: ayrıştırma bir bütün olarak
başarılı ya da baştan sona hiç tamamlanmamış olarak sonuçlanmıyor, **kısmi** kalıyor — durma
noktasından önceki bayraklar okunmuş oluyor, sonrasındakiler hiç görülmüyor.

`kume.SetOutput(io.Discard)` çağrısı burada da aynı gerekçeyle duruyor: `flag.ContinueOnError`
modunda ayrıştırıcı normalde hata metnini kendi yazdığı bir akışa basıyor, ve bu metin hangi
bayrağın tanınmadığını içeriyor — sürüme bağlı bir biçimde. Ölçülen tek şey `hata != nil`
sonucu; hata metninin kendisi hiçbir yere yazılmıyor.

## Alt Komut Yapısı: Her Alt Komutun Kendi Bayrak Kümesi

Tek bir bayrak kümesi tek bir düz komut için yeterli, ama birden çok alt işlevi olan bir
araç genelde **alt komut** yapısını kullanıyor — ilk argüman bir işlevin adı, geri kalanı o
işleve özgü bayraklar. Bu yapının kendisi dilin bir özelliği değil, `flag.NewFlagSet`in
bağımsız kümeler döndürebilmesinin doğal bir sonucu: her alt komuda kendi kümesi veriliyor,
ve bir kümede bildirilen bir bayrak ötekinde hiç var olmuyor.

**SS22.** — İki alt komut (`ekle`, `listele`) kendi bayrak kümesiyle çağrılıyor; sonra
`ekle`nin kendi bayrağı (`-adet`) `listele`nin kümesine verilip tanınmadığı ölçülüyor.

```go
// altkomut.go — her alt komut kendi bayrak kumesini tasiyor, biri otekinde taninmiyor
package main

import (
	"flag"
	"fmt"
	"io"
)

func main() {
	ekleKumesi := flag.NewFlagSet("ekle", flag.ContinueOnError)
	ekleKumesi.SetOutput(io.Discard)
	ekleAd := ekleKumesi.String("ad", "", "urun adi")
	ekleAdet := ekleKumesi.Int("adet", 1, "adet")

	listeleKumesi := flag.NewFlagSet("listele", flag.ContinueOnError)
	listeleKumesi.SetOutput(io.Discard)
	listeleFiltre := listeleKumesi.String("filtre", "", "filtre")

	komutlar := map[string]*flag.FlagSet{"ekle": ekleKumesi, "listele": listeleKumesi}

	girdi1 := []string{"ekle", "-ad", "vida", "-adet", "20"}
	komutlar[girdi1[0]].Parse(girdi1[1:])
	fmt.Println("-- alt komut: ekle, kendi bayrak kumesi --")
	fmt.Printf("ad=%s adet=%d\n", *ekleAd, *ekleAdet)

	girdi2 := []string{"listele", "-filtre", "aktif"}
	komutlar[girdi2[0]].Parse(girdi2[1:])
	fmt.Println("-- alt komut: listele, kendi bayrak kumesi --")
	fmt.Printf("filtre=%s\n", *listeleFiltre)

	girdi3 := []string{"listele", "-adet", "5"}
	hata3 := komutlar[girdi3[0]].Parse(girdi3[1:])
	fmt.Println("-- listele kendi kumesinde 'adet' bayragini hic tanimiyor --")
	fmt.Println("hata verdi mi:", hata3 != nil)
}
```

```
-- alt komut: ekle, kendi bayrak kumesi --
ad=vida adet=20
-- alt komut: listele, kendi bayrak kumesi --
filtre=aktif
-- listele kendi kumesinde 'adet' bayragini hic tanimiyor --
hata verdi mi: true
```

Alt komut adının kendisi (`"ekle"`, `"listele"`) hiçbir bayrak kümesinin parçası değil —
elle kurulmuş dizginin **ilk** elemanı, ayrıştırıcıya hiç verilmeden, çağrılacak kümeyi
seçmek için kullanılıyor; ayrıştırıcının gördüğü yalnızca dizginin geri kalanı
(`girdi1[1:]`). `ekle` kümesi `-ad` ve `-adet` bayraklarını tanıyor, `listele` kümesi yalnız
`-filtre`yi. Üçüncü çağrı bu ayrımı doğruluyor: `-adet` bayrağı `ekle`nin kümesinde geçerli
bir bayrak, ama `listele`nin kümesine verildiğinde ayrıştırıcı onu hiç tanımıyor ve
`bilinmeyen` bölümündeki aynı hatayı döndürüyor. İki küme aynı pakette, aynı `main`
fonksiyonunda tanımlanmış olsa da birbirinden tamamen bağımsız — biri ötekinin bildirdiği
hiçbir bayrağı miras almıyor.

## Sınırlayıcı Ölçüm: Tip Geri Kurulur, Anlam Geri Kurulmaz

Önceki üç ölçüm ayrıştırıcının bir dizgiden **beklediği tipi** doğru geri kurduğunu gösterdi.
Ama "beklenen tip" ile "doğru değer" aynı şey değil: ayrıştırıcı bir dizginin sözdizimsel
olarak o tipe uyup uymadığına bakıyor, değerin anlamlı olup olmadığına hiç bakmıyor.

**SS23.** — `adet` bayrağına negatif bir dizgi (`"-3"`) veriliyor; ayrıştırıcı bunu geçerli
bir tam sayı olarak kabul edip hiçbir hata döndürmüyor.

```go
// anlam.go — ayristirici beklenen tipi geri kurur, degerin anlamini degil
package main

import (
	"flag"
	"fmt"
	"io"
)

func main() {
	kume := flag.NewFlagSet("olcum", flag.ContinueOnError)
	kume.SetOutput(io.Discard)
	adet := kume.Int("adet", 0, "siparis adedi")

	girdi := []string{"-adet", "-3"}
	hata := kume.Parse(girdi)

	fmt.Println("-- ayristirici beklenen tipi geri kurar, degerin anlamini degil --")
	fmt.Println("ayristirma hata verdi mi:", hata != nil)
	fmt.Printf("adet=%d tip=%T\n", *adet, *adet)
}
```

```
-- ayristirici beklenen tipi geri kurar, degerin anlamini degil --
ayristirma hata verdi mi: false
adet=-3 tip=int
```

`-3` dizgisi bir tam sayının sözdizimine tastamam uyuyor — işaret, ardından rakamlar —
bu yüzden `kume.Int`in ayrıştırma mantığı onu sorunsuz kabul ediyor ve `adet` değişkeni
`-3` değerini, `int` tipinde, hiçbir hata olmadan alıyor. Ama bir sipariş adedinin negatif
olması alanın **anlamı** açısından geçersiz; bu geçersizliği ayrıştırıcı hiç bilmiyor, çünkü
ayrıştırıcının tek işi dizgiyi bildirilen tipe **çevirmek**, o tipin değer aralığını
sınırlı tutan bir kural uygulamak değil. Aynı durum önceki derslerde de görüldü: yapı etiketi
bir alanın adını taşıyordu ama değerin geçerliliğini denetlemiyordu, sürücünün taraması bir
sütunun tipini geri kuruyordu ama içindeki sayının anlamlı olup olmadığını sormuyordu. Bu
ders o örüntüyü kapatıyor — geçerli bir aralık denetimi isteniyorsa, bu denetim ayrıştırıcının
işi değil, ayrıştırılan değeri kullanan kodun kendi işi.

## Kurs Kapanışı

On iki ders boyunca bu kursun tek sorusu şuydu: bir değer sınırı geçerken tip bilgisine ne
oluyor? Ortak tanımın üç iddiası bu soruya üç yanıt verdi. Birincisi: sınırı geçen tip
bilgisi kural olarak kayboluyor — ortak ölçümde on üç geçişin yedisinde karşı tarafa yalnız
bayt ya da metin ulaştı, programın içindeki bir tip sınırın ötesinde bir sayı dizisine ya da
bir satıra indirgendi. İkincisi: kaybolan bilgi geri kurulabiliyor, ama bunu yapan şey her
seferinde tarifi tutan taraf oldu — yapı etiketi, hedef tipin kendisi, ayrıştırıcının
beklediği tip, taramanın indirgediği tip; ortak ölçümde beş geçiş bu yolla yeniden kuruldu.
Üçüncüsü, bu kursa özgü olanı: tip bilgisinin korunduğu tek geçiş, iki tarafın **aynı
tarifi paylaştığı** geçişti — Sözleşme Temelli Servis İletişimi dersi bunu on üç geçişin
yalnız birinde gösterdi.

On iki dersin kendi tablosu, ortak ölçümün on üç geçişiyle birebir aynı çözünürlükte değil:
JSON Dizileştirme dersi tek başına dört alt geçiş ölçtü, bu ders de dört tipi tek derste
ölçtü. Yön yine de aynı — on iki satırın beşi `kayboluyor`, altısı `yeniden kuruluyor`, biri
`korunuyor` sınıfına düştü; çoğunluk hâlâ kayıp ya da tarifle geri kurma tarafında, koruma
yine tek bir satırda kaldı. Sınırlayıcı okuma her derste bir biçimde tekrarlandı: "geri
kuruldu" doğru kuruldu, ya da anlamlı bir değer geldi, demek değil. Bir sürücünün taşıdığı
tip, bir yapı etiketinin taşıdığı alan adı, bir bayrak ayrıştırıcının geri kurduğu tam sayı —
hepsi doğru **tipi** verdi, hiçbiri kaynağın niyet ettiği **anlamı** garanti etmedi.

Kurs aşırı bir genelleme yapmadan kapanıyor. Tip sistemi yalnız sınırın **bu tarafında**
çalışıyor; sınırın öbür tarafında — ağda, diskte, bir sürücüde, bir dizgide — tip diye bir
şey yok, yalnız bayt ve metin var. Geri kurma tarifi her zaman **tutan tarafın** işi, ve o
tarif yanlış ya da eksik olduğunda hiçbir uyarı gelmiyor: alıcıda karşılığı olmayan bir alan
sessizce düşüyor, yanlış bir hedefe tarama çalışma zamanında hata veriyor, negatif bir adet
hiç sorgulanmadan geçiyor. Koruma, en güçlü sonuç, yalnız iki tarafın **aynı** tarifi
paylaşmasına bağlı — ve bu paylaşımın kendisi kursun hiçbir dersinde otomatik değildi, hep
ayrıca kurulması gereken bir şeydi.

| Ders | Ölçülen geçiş | Sonucu | Sınırlayıcı ölçüm |
|---|---|---|---|
| HTTP Sunucusu | İsteğin yolu, üstbilgisi ve gövdesinin tip bilgisi taşıyıp taşımadığı | kayboluyor | İçerik tipi üstbilgisi bir ipucu, tip değil — yanlış ipucu sunucuda hiçbir hata üretmiyor |
| HTTP İstemcisi | Yanıt gövdesinin istemci tarafında okunması ve kapatılması | kayboluyor | Gövde bir okuyucu, bir değer değil — ikinci okuma hatasız boş dönüyor |
| JSON Dizileştirme | Yapı etiketiyle işaretli alanların JSON gidiş-dönüşü | yeniden kuruluyor | "Geri kuruldu" doğru kuruldu demek değil — karşılıksız alan sessizce düşüyor |
| Şablonlar | Aynı yapının iki şablondan geçirilmiş çıktısı | kayboluyor | Alan adı çalışma zamanında aranıyor — olmayan alan hatası çıktının ortasında doğuyor |
| Sözleşme Temelli Servis İletişimi | İki sürecin paylaştığı tarifle üretilen kaynağın alanları | korunuyor | Koruma tarifin dağıtımına bağlı — tarif ayrışırsa geçiş sessizce kayboluyora düşüyor |
| Gerçek Zamanlı İletişim | Uzun süreli bağlantıda itilen mesajın gövdesi | kayboluyor | Çerçeveleme mesajın nerede bittiğini veriyor, içindeki değerin tipini vermiyor |
| Dosya ve Girdi/Çıktı Arayüzleri | Dört kaynağın (dosya, arabellek, dizgi, ağ gövdesi) aynı okuyucudan geçmesi | kayboluyor | Kısmi okuma ile dosya sonu ayrı adımlar — ayrımı yönetmek çağıranın işi |
| Gömülü Kaynaklar | Kaynak dosyanın üç Go tipine derleme zamanında bağlanması | yeniden kuruluyor | İkili, kaynak dosya silindikten sonra da aynı içeriği üretiyor — bağ derleme zamanında kuruldu |
| Zaman İşlemleri | Bir anın metne dönüp geri gelmesi | yeniden kuruluyor | Ofset yeniden kuruluyor ama bölge adı taşınmıyor — `Equal` eşit, `==` ve `String()` farklı |
| Yapılandırılmış Günlükleme | Aynı olayın düz metin ve anahtar-değer biçiminde yazılması | yeniden kuruluyor | Alan adı korunuyor, tip korunmuyor — geri kurma okuyanın kendi tarifine bağlı |
| Veritabanı Erişimi | Sürücüden gelen beş sütunun hedef tipe taranması | yeniden kuruluyor | Tarama hedefin tipine bakıyor, kaynağın tipine değil — uyumsuz hedef çalışma zamanında hata veriyor |
| Komut Satırı Uygulamaları | Bayrak kümesine verilen dizginin dört tipe ayrıştırılması | yeniden kuruluyor | Ayrıştırıcı beklenen tipi geri kuruyor, değerin anlamını değil — negatif adet hatasız geçiyor |

## Özet

- Bayrak ayrıştırıcısı, elle kurulmuş bir dizgi dizisinden dört tipi (tam sayı, mantıksal,
  süre, dizgi) önceden bildirilen bayrak tanımlarına göre geri kurdu; `os.Args` hiçbir yerde
  okunmadı.
- Tanınmayan bir bayrak ayrıştırmayı olduğu noktada durdurdu: durma noktasından önceki
  bayraklar okundu, sonrasındakiler hiç işlenmedi.
- Alt komut yapısında her alt komut kendi bağımsız bayrak kümesini taşıdı; bir kümede
  bildirilen bir bayrak ötekinde hiç tanınmadı.
- Sınırlayıcı ölçüm: ayrıştırıcı bir dizginin beklenen tipe sözdizimsel olarak uyup
  uymadığına baktı, değerin anlamlı olup olmadığına bakmadı — negatif bir adet hatasız geçti.
- Kurs on iki ders boyunca aynı soruyu on iki ayrı sınırda sordu ve üç sonuçtan birine
  yazdı; çoğunluk kayboluyor ya da yeniden kuruluyor sınıfında kaldı, koruma yalnız iki
  tarafın aynı tarifi paylaştığı tek bir geçişte görüldü.
- Kurs on iki dersin ölçtüğü yanıtları tek bir tabloda topladı; her satır kendi kaynak
  dersinden okundu.
