<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sonsuzus.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://sonsuzus.github.io/" rel="alternate" type="text/html" /><updated>2026-07-24T07:13:22+00:00</updated><id>https://sonsuzus.github.io/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">Arayüzler ve Çok Biçimlilik: Kim Olduğun Değil, Ne Yapabildiğin Önemli</title><link href="https://sonsuzus.github.io/posts/arayuzler-ve-cok-bicimlilik-kim-oldugun-degil-ne-yapabildigin-onemli/" rel="alternate" type="text/html" title="Arayüzler ve Çok Biçimlilik: Kim Olduğun Değil, Ne Yapabildiğin Önemli" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/arayuzler-ve-cok-bicimlilik-kim-oldugun-degil-ne-yapabildigin-onemli</id><content type="html" xml:base="https://sonsuzus.github.io/posts/arayuzler-ve-cok-bicimlilik-kim-oldugun-degil-ne-yapabildigin-onemli/"><![CDATA[<p>Yazılım dünyasında bazen nesnelere fazla kimlik sorarız: “Sen gerçekten User mısın, Admin misin, Robot musun?” Oysa esnek tasarımın daha havalı sorusu şudur: “Ne yapabiliyorsun?” Arayüzler, tam da bu bakış açısını kodun merkezine koyar. Bir nesnenin sınıf soy ağacına değil, sunduğu davranış sözleşmesine odaklanır. Böylece kodumuz daha az dedikoducu, daha çok iş bitirici olur.
``</p>

<p>Arayüzü teorik olarak bir <strong>sözleşme</strong> gibi düşünebiliriz. Bir arayüz, “Beni uygulayan her yapı şu metotları, özellikleri veya davranışları sağlayacak” der. Ancak bunu nasıl yapacağını söylemez. Matematiksel olarak bir arayüzü, nesneler kümesinden davranışlar kümesine kurulan bir beklenti ilişkisi gibi görebiliriz: $I = {b_1, b_2, b_3}$ ise, bu arayüzü uygulayan her nesne bu davranışları sağlamalıdır. Burada önemli olan nesnenin iç yapısı değil, dışarıdan gözlemlenebilen davranışıdır.</p>

<p>Çok biçimlilik yani polymorphism ise aynı mesajın farklı nesnelerde farklı şekillerde çalışabilmesidir. Örneğin <code class="language-plaintext highlighter-rouge">draw()</code> çağrısı bir daireyi yuvarlak, bir kareyi köşeli çizer. Çağıran kod için önemli olan şeklin gerçek sınıfı değil, çizilebilir olmasıdır. Bu yaklaşım $Kod -&gt; Arayüz$ bağımlılığını güçlendirir, $Kod -&gt; SomutSınıf$ bağımlılığını azaltır.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Soru</th>
      <th>Sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sınıfa odaklanmak</td>
      <td>“Bu nesne hangi tür?”</td>
      <td>Daha sıkı bağımlılık</td>
    </tr>
    <tr>
      <td>Arayüze odaklanmak</td>
      <td>“Bu nesne ne yapabilir?”</td>
      <td>Daha esnek tasarım</td>
    </tr>
    <tr>
      <td>Kalıtım merkezli tasarım</td>
      <td>“Kimden türedi?”</td>
      <td>Hiyerarşi baskısı</td>
    </tr>
    <tr>
      <td>Davranış merkezli tasarım</td>
      <td>“Hangi sözleşmeyi sağlar?”</td>
      <td>Değişime açıklık</td>
    </tr>
  </tbody>
</table>

<p>Basit bir TypeScript örneği düşünelim:</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">interface</span> <span class="nx">Payable</span> <span class="p">{</span>
  <span class="nf">calculatePayment</span><span class="p">():</span> <span class="kr">number</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Employee</span> <span class="k">implements</span> <span class="nx">Payable</span> <span class="p">{</span>
  <span class="nf">constructor</span><span class="p">(</span><span class="k">private</span> <span class="nx">salary</span><span class="p">:</span> <span class="kr">number</span><span class="p">)</span> <span class="p">{}</span>

  <span class="nf">calculatePayment</span><span class="p">():</span> <span class="kr">number</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">salary</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Freelancer</span> <span class="k">implements</span> <span class="nx">Payable</span> <span class="p">{</span>
  <span class="nf">constructor</span><span class="p">(</span><span class="k">private</span> <span class="nx">hourlyRate</span><span class="p">:</span> <span class="kr">number</span><span class="p">,</span> <span class="k">private</span> <span class="nx">hours</span><span class="p">:</span> <span class="kr">number</span><span class="p">)</span> <span class="p">{}</span>

  <span class="nf">calculatePayment</span><span class="p">():</span> <span class="kr">number</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">hourlyRate</span> <span class="o">*</span> <span class="k">this</span><span class="p">.</span><span class="nx">hours</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nf">printPayment</span><span class="p">(</span><span class="nx">entity</span><span class="p">:</span> <span class="nx">Payable</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Ödeme: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">entity</span><span class="p">.</span><span class="nf">calculatePayment</span><span class="p">());</span>
<span class="p">}</span>

<span class="nf">printPayment</span><span class="p">(</span><span class="k">new</span> <span class="nc">Employee</span><span class="p">(</span><span class="mi">40000</span><span class="p">));</span>
<span class="nf">printPayment</span><span class="p">(</span><span class="k">new</span> <span class="nc">Freelancer</span><span class="p">(</span><span class="mi">750</span><span class="p">,</span> <span class="mi">32</span><span class="p">));</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">printPayment</code> fonksiyonu, parametrenin <code class="language-plaintext highlighter-rouge">Employee</code> ya da <code class="language-plaintext highlighter-rouge">Freelancer</code> olmasını umursamaz. Tek şartı vardır: <code class="language-plaintext highlighter-rouge">Payable</code> davranışını sağlaması. Bu fonksiyonun zihni oldukça rahattır; CV sormaz, sadece ödeme hesaplayabiliyor musun diye bakar.</p>

<p>Bu tasarımın gücü, <strong>Açık/Kapalı Prensibi</strong> ile birleştiğinde ortaya çıkar. Yazılım birimleri genişletmeye açık, değiştirmeye kapalı olmalıdır. Yeni bir <code class="language-plaintext highlighter-rouge">Consultant</code> sınıfı eklediğimizde <code class="language-plaintext highlighter-rouge">printPayment</code> fonksiyonunu değiştirmiyorsak doğru yoldayız demektir. Teorik olarak bu, sistemin yeni türler karşısında kararlı kalmasıdır: $YeniTip + EskiArayüz = DahaAzKırılma$.</p>

<table>
  <thead>
    <tr>
      <th>Tasarım ilkesi</th>
      <th>Arayüzle ilişkisi</th>
      <th>Pratik fayda</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dependency Inversion</td>
      <td>Üst seviye modüller somuta değil soyuta bağlıdır</td>
      <td>Test edilebilirlik artar</td>
    </tr>
    <tr>
      <td>Open/Closed</td>
      <td>Yeni davranışlar mevcut kodu bozmadan eklenir</td>
      <td>Bakım kolaylaşır</td>
    </tr>
    <tr>
      <td>Liskov Substitution</td>
      <td>Arayüzü uygulayan nesne beklenen davranışı bozmaz</td>
      <td>Güvenilir polymorphism</td>
    </tr>
    <tr>
      <td>Interface Segregation</td>
      <td>Büyük arayüzler küçük parçalara ayrılır</td>
      <td>Gereksiz bağımlılık azalır</td>
    </tr>
  </tbody>
</table>

<p>Ancak arayüz kullanmak her derde deva büyülü bir iksir değildir. Gereksiz arayüzler, projede “soyutlama sisi” oluşturabilir. Eğer sadece tek bir sınıfınız varsa ve değişim ihtimali düşükse, hemen arayüz üretmek erken mühendislik olabilir. İyi arayüz, gerçek bir değişim eksenini temsil eder. Yani “ileride farklı ödeme stratejileri olabilir” diyorsanız <code class="language-plaintext highlighter-rouge">Payable</code> anlamlıdır; ama “belki bir gün kahve makinesi de ödeme hesaplar” diyorsanız biraz sakinleşmek gerekebilir.</p>

<p>Arayüzlerin bir diğer güzelliği testlerde görülür. Somut veritabanı bağlantısı yerine <code class="language-plaintext highlighter-rouge">Repository</code> arayüzüne bağımlı kod, test sırasında sahte bir bellek içi nesneyle çalışabilir. Böylece kodun davranışını izole ederiz. Bu da yazılımı daha ölçülebilir yapar; çünkü test maliyeti kabaca $Maliyet = Kurulum + Bağımlılık + Bekleme$ ise, arayüzler özellikle bağımlılık ve bekleme kısmını azaltır.</p>

<p>Sonuç olarak arayüzler, yazılım tasarımında kimlik kontrolünden davranış kontrolüne geçiştir. Çok biçimlilikle birleştiğinde, aynı kodun farklı nesnelerle uyumlu çalışmasını sağlar. Bu yaklaşım, gelecekte gelecek yeni sınıflara kapıyı açık bırakırken mevcut kodu sakin ve kararlı tutar. Kısacası iyi tasarlanmış bir arayüz şunu söyler: “Bana nereden geldiğini anlatma, ne yapabildiğini göster.”</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="arayüzler" /><category term="çok biçimlilik" /><category term="yazılım tasarımı" /><summary type="html"><![CDATA[Yazılım dünyasında bazen nesnelere fazla kimlik sorarız: “Sen gerçekten User mısın, Admin misin, Robot musun?” Oysa esnek tasarımın daha havalı sorusu şudur: “Ne yapabiliyorsun?” Arayüzler, tam da bu bakış açısını kodun merkezine koyar. Bir nesnenin sınıf soy ağacına değil, sunduğu davranış sözleşmesine odaklanır. Böylece kodumuz daha az dedikoducu, daha çok iş bitirici olur.]]></summary></entry><entry><title type="html">Diziler ve Dilimler: Bellekte Sabit Kutular, Esnek Pencereler</title><link href="https://sonsuzus.github.io/posts/diziler-ve-dilimler-bellekte-sabit-kutular-esnek-pencereler/" rel="alternate" type="text/html" title="Diziler ve Dilimler: Bellekte Sabit Kutular, Esnek Pencereler" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/diziler-ve-dilimler-bellekte-sabit-kutular-esnek-pencereler</id><content type="html" xml:base="https://sonsuzus.github.io/posts/diziler-ve-dilimler-bellekte-sabit-kutular-esnek-pencereler/"><![CDATA[<p>Bir veri koleksiyonunu saklamak istediğimizde aklımıza ilk gelen yapı genellikle dizidir; ama Go gibi dillerde sahneye bir de dilimler, yani slices çıkar. Dizi, bellekte yan yana duran sabit sayıda kutu gibidir; dilim ise bu kutuların tamamını ya da bir bölümünü gösteren akıllı bir pencere. Aralarındaki farkı anlamak, sadece sözdizimini değil, performans ve bellek davranışını da doğru okumayı sağlar.
``</p>

<h2 id="teorik-temel-boyut-mu-esneklik-mi">Teorik Temel: Boyut mu, Esneklik mi?</h2>

<p>Dizi, uzunluğu türünün parçası olan sabit boyutlu bir veri yapısıdır. Go’da <code class="language-plaintext highlighter-rouge">[3]int</code> ile <code class="language-plaintext highlighter-rouge">[4]int</code> farklı türlerdir. Yani derleyici için “3 elemanlı int dizisi” ile “4 elemanlı int dizisi” aynı ailenin kuzenleri bile değildir; tamamen ayrı kimliklere sahiptir.</p>

<p>Dilim ise kendi başına veriyi doğrudan taşımaz. Arkasında genellikle bir dizi bulunur ve dilim bu dizinin belirli bir aralığına referans verir. Bir slice üç parçalı küçük bir başlık gibi düşünülebilir:</p>

<ul>
  <li>işaretçi: alttaki dizide başlangıç konumu,</li>
  <li>uzunluk: şu an görünen eleman sayısı,</li>
  <li>kapasite: başlangıçtan itibaren kullanılabilecek maksimum alan.</li>
</ul>

<p>Matematiksel olarak temel kural şudur: $0 \le len(slice) \le cap(slice)$. Yani uzunluk kapasiteyi aşamaz; ama <code class="language-plaintext highlighter-rouge">append</code> ile kapasite yetmezse Go yeni ve daha büyük bir alttaki dizi ayırabilir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Array</th>
      <th>Slice</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Boyut</td>
      <td>Sabit</td>
      <td>Dinamik görünümlü</td>
    </tr>
    <tr>
      <td>Tür bilgisi</td>
      <td>Boyut türün parçasıdır</td>
      <td>Boyut türün parçası değildir</td>
    </tr>
    <tr>
      <td>Kopyalama</td>
      <td>Tüm elemanlar kopyalanır</td>
      <td>Başlık kopyalanır, veri paylaşılabilir</td>
    </tr>
    <tr>
      <td>Bellek modeli</td>
      <td>Doğrudan veri</td>
      <td>Alttaki diziye referans</td>
    </tr>
    <tr>
      <td>Esneklik</td>
      <td>Düşük</td>
      <td>Yüksek</td>
    </tr>
  </tbody>
</table>

<h2 id="diziler-sabit-boyutlu-disiplin">Diziler: Sabit Boyutlu Disiplin</h2>

<p>Diziler, özellikle boyutun kesin bilindiği durumlarda harikadır. Örneğin RGB renk değeri için <code class="language-plaintext highlighter-rouge">[3]uint8</code> gayet anlamlıdır. Çünkü kırmızı, yeşil ve mavi olmak üzere tam üç kanal vardır; dördüncü eleman beklenmez.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">updateArray</span><span class="p">(</span><span class="n">a</span> <span class="p">[</span><span class="m">3</span><span class="p">]</span><span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">a</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">=</span> <span class="m">99</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">nums</span> <span class="o">:=</span> <span class="p">[</span><span class="m">3</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span><span class="m">1</span><span class="p">,</span> <span class="m">2</span><span class="p">,</span> <span class="m">3</span><span class="p">}</span>
    <span class="n">updateArray</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span>
    <span class="nb">println</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="m">0</span><span class="p">])</span> <span class="c">// 1</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu örnekte <code class="language-plaintext highlighter-rouge">updateArray</code> fonksiyonuna dizi gönderildiğinde tüm dizi kopyalanır. Fonksiyon içindeki değişiklik dışarıdaki <code class="language-plaintext highlighter-rouge">nums</code> dizisini etkilemez. Bu davranış güvenlidir ama büyük dizilerde maliyetli olabilir. Eğer $n$ elemanlı bir dizi kopyalanıyorsa işlem maliyeti yaklaşık $O(n)$ olur.</p>

<h2 id="dilimler-esnek-ve-paylaşımcı-pencereler">Dilimler: Esnek ve Paylaşımcı Pencereler</h2>

<p>Dilimlerde durum daha hareketlidir. Slice değeri kopyalansa bile alttaki dizi çoğu zaman aynı kalır. Bu yüzden bir fonksiyona slice gönderdiğinizde eleman değişiklikleri dışarıdan görülebilir.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">updateSlice</span><span class="p">(</span><span class="n">s</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">s</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="o">=</span> <span class="m">99</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">nums</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">int</span><span class="p">{</span><span class="m">1</span><span class="p">,</span> <span class="m">2</span><span class="p">,</span> <span class="m">3</span><span class="p">}</span>
    <span class="n">updateSlice</span><span class="p">(</span><span class="n">nums</span><span class="p">)</span>
    <span class="nb">println</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="m">0</span><span class="p">])</span> <span class="c">// 99</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">s</code> aslında slice başlığının kopyasıdır; fakat başlığın gösterdiği alttaki dizi aynıdır. Bu nedenle <code class="language-plaintext highlighter-rouge">s[0] = 99</code>, orijinal veriyi değiştirir. İşte slice’ların “referans gibi davranıyor” denmesinin sebebi budur. Tam anlamıyla referans türü demek yerine, “referans taşıyan küçük bir descriptor” demek daha doğrudur.</p>

<h2 id="append-ve-kapasite-sürprizi">Append ve Kapasite Sürprizi</h2>

<p>Slice’ların en eğlenceli tarafı <code class="language-plaintext highlighter-rouge">append</code> ile büyüyebilmesidir; ama burada küçük bir numara vardır. Kapasite yetiyorsa aynı alttaki dizi kullanılır. Yetmiyorsa yeni bir dizi oluşturulur ve elemanlar oraya taşınır.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">a</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">int</span><span class="p">{</span><span class="m">10</span><span class="p">,</span> <span class="m">20</span><span class="p">,</span> <span class="m">30</span><span class="p">}</span>
    <span class="n">b</span> <span class="o">:=</span> <span class="n">a</span><span class="p">[</span><span class="o">:</span><span class="m">2</span><span class="p">]</span>

    <span class="n">b</span> <span class="o">=</span> <span class="nb">append</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="m">99</span><span class="p">)</span>

    <span class="nb">println</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="m">2</span><span class="p">])</span> <span class="c">// kapasite yeterse 99 olabilir</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu örnekte <code class="language-plaintext highlighter-rouge">b</code>, <code class="language-plaintext highlighter-rouge">a</code> dizisinin ilk iki elemanını gösterir. Eğer <code class="language-plaintext highlighter-rouge">b</code> için kapasite yeterliyse <code class="language-plaintext highlighter-rouge">append</code>, üçüncü konuma <code class="language-plaintext highlighter-rouge">99</code> yazar ve <code class="language-plaintext highlighter-rouge">a[2]</code> de değişmiş gibi görünür. Bu, slice paylaşımının hem süper gücü hem de potansiyel tuzağıdır.</p>

<table>
  <thead>
    <tr>
      <th>Senaryo</th>
      <th>Sonuç</th>
      <th>Dikkat Edilecek Nokta</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Slice elemanı değiştirme</td>
      <td>Alttaki dizi değişir</td>
      <td>Diğer slice’lar etkilenebilir</td>
    </tr>
    <tr>
      <td>Append, kapasite yeterli</td>
      <td>Aynı dizi kullanılır</td>
      <td>Yan etki oluşabilir</td>
    </tr>
    <tr>
      <td>Append, kapasite yetersiz</td>
      <td>Yeni dizi ayrılır</td>
      <td>Eski slice etkilenmeyebilir</td>
    </tr>
    <tr>
      <td>Array fonksiyona geçme</td>
      <td>Tam kopya</td>
      <td>Büyük veri için pahalıdır</td>
    </tr>
  </tbody>
</table>

<h2 id="ne-zaman-hangisi">Ne Zaman Hangisi?</h2>

<p>Boyut gerçekten sabitse ve bu bilgi programın anlamının parçasıysa array iyi seçimdir. Örneğin matris boyutu, kriptografik bloklar veya sabit protokol alanları buna uygundur. Ancak çoğu uygulama kodunda veri miktarı çalışma zamanında değişir: kullanıcı listeleri, dosyadan okunan satırlar, API sonuçları… Bu durumda slice çok daha pratiktir.</p>

<p>Kısa özetle: array, bellekte düzenli ve sabit bir apartman; slice ise bu apartmanın odalarına bakan esnek bir emlak danışmanıdır. Danışman hafiftir, kolay kopyalanır; ama hangi odayı gösterdiğini unutursanız yanlış duvarı boyayabilirsiniz. Go’da güçlü ve hatasız kod yazmanın yolu, bu küçük pencerenin arkasındaki büyük diziyi her zaman akılda tutmaktan geçer.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Go" /><category term="Arrays" /><category term="Slices" /><category term="Bellek Yönetimi" /><summary type="html"><![CDATA[Bir veri koleksiyonunu saklamak istediğimizde aklımıza ilk gelen yapı genellikle dizidir; ama Go gibi dillerde sahneye bir de dilimler, yani slices çıkar. Dizi, bellekte yan yana duran sabit sayıda kutu gibidir; dilim ise bu kutuların tamamını ya da bir bölümünü gösteren akıllı bir pencere. Aralarındaki farkı anlamak, sadece sözdizimini değil, performans ve bellek davranışını da doğru okumayı sağlar.]]></summary></entry><entry><title type="html">Eşzamanlılık Temelleri ve Goroutines: Go ile Çok Çekirdekli Gücü Uyandırmak</title><link href="https://sonsuzus.github.io/posts/eszamanlilik-temelleri-ve-goroutines-go-ile-cok-cekirdekli-gucu-uyandirmak/" rel="alternate" type="text/html" title="Eşzamanlılık Temelleri ve Goroutines: Go ile Çok Çekirdekli Gücü Uyandırmak" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/eszamanlilik-temelleri-ve-goroutines-go-ile-cok-cekirdekli-gucu-uyandirmak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/eszamanlilik-temelleri-ve-goroutines-go-ile-cok-cekirdekli-gucu-uyandirmak/"><![CDATA[<p>Bilgisayarlarımız artık tek bir hızlı çekirdekten ibaret değil; çoğu makinede birden fazla çekirdek sessizce iş bekliyor. Go dilinin goroutine yaklaşımı tam da burada devreye girer: işletim sistemi iş parçacıklarına göre çok daha hafif görevler başlatarak aynı anda birçok işi düzenli, okunabilir ve verimli biçimde yürütmemizi sağlar.
``
Eşzamanlılık, birden fazla işin aynı zaman aralığında ilerlemesi fikridir. Paralellik ise bu işlerin gerçekten aynı anda, farklı çekirdeklerde çalışmasıdır. Yani eşzamanlılık bir tasarım modeli, paralellik ise donanım desteğiyle gerçekleşen çalışma biçimidir. Go bu ayrımı çok güzel saklar: siz <code class="language-plaintext highlighter-rouge">go</code> anahtar kelimesiyle goroutine başlatırsınız, Go çalışma zamanı bunları uygun işletim sistemi thread’lerine dağıtır.</p>

<p>Basit bir matematiksel bakış atalım. Bir programın toplam süresi $T$ olsun. Eğer işin paralelleştirilebilir kısmı $p$, işlemci çekirdeği sayısı da $n$ ise Amdahl yasasına göre teorik hızlanma yaklaşık $Hiz = 1 / ((1-p)+p/n)$ olur. Yani her şeyi paralel yapamayız; ama doğru parçaları eşzamanlı tasarlarsak ciddi kazanç elde ederiz.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Ne Anlama Gelir?</th>
      <th>Go’daki Karşılığı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Thread</td>
      <td>İşletim sistemi tarafından yönetilen ağır yürütme birimi</td>
      <td>OS thread</td>
    </tr>
    <tr>
      <td>Goroutine</td>
      <td>Go runtime tarafından yönetilen hafif görev</td>
      <td><code class="language-plaintext highlighter-rouge">go fonksiyon()</code></td>
    </tr>
    <tr>
      <td>Eşzamanlılık</td>
      <td>İşlerin birlikte ilerlemesi</td>
      <td>Goroutine + channel</td>
    </tr>
    <tr>
      <td>Paralellik</td>
      <td>İşlerin fiziksel olarak aynı anda çalışması</td>
      <td>Çok çekirdek + scheduler</td>
    </tr>
  </tbody>
</table>

<p>Bir goroutine başlatmak şaşırtıcı derecede kolaydır. Aşağıdaki örnekte <code class="language-plaintext highlighter-rouge">selamVer</code> fonksiyonu ana akıştan bağımsız çalışır. <code class="language-plaintext highlighter-rouge">time.Sleep</code> burada sadece örneğin bitmeden goroutine’in çıktısını görebilmemiz için kullanılır; gerçek projelerde genellikle <code class="language-plaintext highlighter-rouge">sync.WaitGroup</code> tercih edilir.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"fmt"</span>
    <span class="s">"time"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">selamVer</span><span class="p">(</span><span class="n">kim</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">for</span> <span class="n">i</span> <span class="o">:=</span> <span class="m">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="m">3</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span> <span class="p">{</span>
        <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"Merhaba"</span><span class="p">,</span> <span class="n">kim</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
        <span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">300</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Millisecond</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">go</span> <span class="n">selamVer</span><span class="p">(</span><span class="s">"Goroutine"</span><span class="p">)</span>

    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"Ana program çalışıyor"</span><span class="p">)</span>
    <span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">1</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">go selamVer(...)</code> satırı fonksiyonu yeni bir goroutine olarak çalıştırır. Ana program beklemek zorunda değildir; kendi yoluna devam eder. İşte goroutine’lerin hafifliği burada parlar: binlerce goroutine başlatmak, binlerce işletim sistemi thread’i açmaktan çok daha ekonomiktir.</p>

<p>Ancak süper güçlerin yan etkileri vardır. Birden fazla goroutine aynı veriye yazmaya çalışırsa yarış durumu, yani race condition oluşabilir. Mesela iki kişi aynı deftere aynı anda not almaya çalışırsa sonuç karışabilir. Go’da bu tür durumlar için <code class="language-plaintext highlighter-rouge">channel</code>, <code class="language-plaintext highlighter-rouge">mutex</code> ve <code class="language-plaintext highlighter-rouge">WaitGroup</code> gibi araçlar kullanılır.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"fmt"</span>
    <span class="s">"sync"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">isYap</span><span class="p">(</span><span class="n">id</span> <span class="kt">int</span><span class="p">,</span> <span class="n">wg</span> <span class="o">*</span><span class="n">sync</span><span class="o">.</span><span class="n">WaitGroup</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">defer</span> <span class="n">wg</span><span class="o">.</span><span class="n">Done</span><span class="p">()</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"İş başladı:"</span><span class="p">,</span> <span class="n">id</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">var</span> <span class="n">wg</span> <span class="n">sync</span><span class="o">.</span><span class="n">WaitGroup</span>

    <span class="k">for</span> <span class="n">i</span> <span class="o">:=</span> <span class="m">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="m">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span> <span class="p">{</span>
        <span class="n">wg</span><span class="o">.</span><span class="n">Add</span><span class="p">(</span><span class="m">1</span><span class="p">)</span>
        <span class="k">go</span> <span class="n">isYap</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">wg</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="n">wg</span><span class="o">.</span><span class="n">Wait</span><span class="p">()</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="s">"Tüm işler tamamlandı"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">WaitGroup</code>, ana programın tüm goroutine’ler bitene kadar beklemesini sağlar. <code class="language-plaintext highlighter-rouge">wg.Add(1)</code> yeni bir iş eklendiğini, <code class="language-plaintext highlighter-rouge">defer wg.Done()</code> işin tamamlandığını, <code class="language-plaintext highlighter-rouge">wg.Wait()</code> ise herkes dönene kadar beklenmesi gerektiğini söyler.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th>Kötü Yaklaşım</th>
      <th>Daha Sağlıklı Yaklaşım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ana program erken bitiyor</td>
      <td>Rastgele <code class="language-plaintext highlighter-rouge">Sleep</code> kullanmak</td>
      <td><code class="language-plaintext highlighter-rouge">sync.WaitGroup</code> kullanmak</td>
    </tr>
    <tr>
      <td>Ortak veri değişiyor</td>
      <td>Kontrolsüz yazmak</td>
      <td><code class="language-plaintext highlighter-rouge">Mutex</code> veya channel kullanmak</td>
    </tr>
    <tr>
      <td>Çok fazla iş var</td>
      <td>Tek tek senkron çalıştırmak</td>
      <td>Worker pool kurmak</td>
    </tr>
    <tr>
      <td>Sonuçlar toplanacak</td>
      <td>Global değişkene yazmak</td>
      <td>Channel ile sonuç taşımak</td>
    </tr>
  </tbody>
</table>

<p>Go’nun scheduler’ı goroutine’leri işletim sistemi thread’leri üzerinde gezdirir. <code class="language-plaintext highlighter-rouge">GOMAXPROCS</code> değeri aynı anda kaç OS thread’in Go kodu çalıştırabileceğini belirler. Modern Go sürümlerinde bu değer genellikle makinedeki CPU çekirdeği sayısına göre otomatik ayarlanır. Yani çoğu zaman ayar yapmadan çok çekirdekli gücü kullanmaya başlarsınız.</p>

<p>Sonuç olarak goroutine, Go’nun en keyifli ve güçlü özelliklerinden biridir. Ama amaç her yere <code class="language-plaintext highlighter-rouge">go</code> yazmak değildir. Doğru soru şudur: Bu işler bağımsız mı, bekleme içeriyor mu, sonuçlar güvenli şekilde birleşiyor mu? Cevap evetse goroutine’ler uygulamanıza roket takabilir. Cevap hayırsa, roket yerine mutfakta havai fişek yakmış olabilirsiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="go" /><category term="goroutines" /><category term="eşzamanlılık" /><summary type="html"><![CDATA[Bilgisayarlarımız artık tek bir hızlı çekirdekten ibaret değil; çoğu makinede birden fazla çekirdek sessizce iş bekliyor. Go dilinin goroutine yaklaşımı tam da burada devreye girer: işletim sistemi iş parçacıklarına göre çok daha hafif görevler başlatarak aynı anda birçok işi düzenli, okunabilir ve verimli biçimde yürütmemizi sağlar.]]></summary></entry><entry><title type="html">Go Kanalları ve Senkronizasyon: Goroutine’ler Arasında Güvenli Veri Trafiği</title><link href="https://sonsuzus.github.io/posts/go-kanallari-ve-senkronizasyon-goroutineler-arasinda-guvenli-veri-trafigi/" rel="alternate" type="text/html" title="Go Kanalları ve Senkronizasyon: Goroutine’ler Arasında Güvenli Veri Trafiği" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/go-kanallari-ve-senkronizasyon-goroutineler-arasinda-guvenli-veri-trafigi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/go-kanallari-ve-senkronizasyon-goroutineler-arasinda-guvenli-veri-trafigi/"><![CDATA[<p>Go dünyasında goroutine’ler sahneye çıktığında ortalık bir anda kalabalıklaşır: aynı anda çalışan fonksiyonlar, paralel iş akışları ve bolca hız! Fakat hızın yanında klasik bir soru gelir: Bu çalışan parçalar birbirleriyle nasıl güvenli konuşacak? Go’nun cevabı nettir: Belleği paylaşarak iletişim kurma; iletişim kurarak belleği paylaş.
``
Bu felsefenin merkezinde <strong>channels</strong>, yani kanallar bulunur. Kanalı, iki goroutine arasında uzanan tip güvenli bir boru gibi düşünebilirsin. Bir goroutine boruya veri bırakır, diğeri o veriyi alır. Böylece aynı değişkene aynı anda erişme, kilit unutma, yarış durumu üretme gibi klasik eşzamanlılık kabusları ciddi ölçüde azalır.</p>

<p>Teorik olarak problem şudur: Birden fazla yürütme birimi aynı belleğe erişirse ve en az biri yazma yaparsa, sonuç zamana bağlı hale gelir. Buna <strong>race condition</strong> deriz. Basitçe ifade edersek, iki işlem $A$ ve $B$ için belirli bir sıra garanti edilmiyorsa sonuç $A \rightarrow B$ veya $B \rightarrow A$ olabilir. Kanallar ise bu sırayı veri alışverişi üzerinden tanımlar. Bir gönderme işlemi, ilgili alma işlemi tamamlanmadan anlamlı biçimde bitmez. Bu da Go bellek modelinde bir tür <strong>happens-before</strong> ilişkisi oluşturur: $send(x) \rightarrow receive(x)$.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Temel fikir</th>
      <th>Risk</th>
      <th>Go’daki araç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Paylaşılan bellek</td>
      <td>Herkes aynı değişkeni okur/yazar</td>
      <td>Race condition, deadlock</td>
      <td><code class="language-plaintext highlighter-rouge">sync.Mutex</code>, <code class="language-plaintext highlighter-rouge">sync.RWMutex</code></td>
    </tr>
    <tr>
      <td>Mesajlaşma</td>
      <td>Goroutine’ler veri gönderip alır</td>
      <td>Yanlış kanal tasarımı, bloklanma</td>
      <td><code class="language-plaintext highlighter-rouge">chan</code>, <code class="language-plaintext highlighter-rouge">select</code></td>
    </tr>
    <tr>
      <td>Atomik işlemler</td>
      <td>Çok küçük kritik işlemler</td>
      <td>Okunabilirlik düşebilir</td>
      <td><code class="language-plaintext highlighter-rouge">sync/atomic</code></td>
    </tr>
  </tbody>
</table>

<p>En basit kanal örneğiyle başlayalım:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="s">"fmt"</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">mesajlar</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="kt">string</span><span class="p">)</span>

    <span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">mesajlar</span> <span class="o">&lt;-</span> <span class="s">"Merhaba kanal!"</span>
    <span class="p">}()</span>

    <span class="n">msg</span> <span class="o">:=</span> <span class="o">&lt;-</span><span class="n">mesajlar</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">make(chan string)</code> ifadesi string taşıyan bir kanal oluşturur. <code class="language-plaintext highlighter-rouge">mesajlar &lt;- ...</code> gönderme, <code class="language-plaintext highlighter-rouge">&lt;-mesajlar</code> ise alma işlemidir. Dikkat çekici nokta şudur: Varsayılan yani <strong>unbuffered</strong> kanal, gönderici ve alıcıyı buluşturur. Gönderen goroutine, biri veriyi alana kadar bekler. Bu davranış, kanalın yalnızca veri taşımasını değil, aynı zamanda senkronizasyon aracı olmasını sağlar.</p>

<p>Kanalları matematiksel olarak küçük bir kuyruk gibi düşünebiliriz. Kapasite $k$ ise kanalda aynı anda en fazla $k$ eleman bulunur. Unbuffered kanal için $k = 0$ kabul edilir; yani veri bekleme salonunda oturamaz, doğrudan teslim edilmelidir.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="s">"fmt"</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">kuyruk</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="kt">int</span><span class="p">,</span> <span class="m">2</span><span class="p">)</span>

    <span class="n">kuyruk</span> <span class="o">&lt;-</span> <span class="m">10</span>
    <span class="n">kuyruk</span> <span class="o">&lt;-</span> <span class="m">20</span>

    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="o">&lt;-</span><span class="n">kuyruk</span><span class="p">)</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="o">&lt;-</span><span class="n">kuyruk</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu örnekte kanalın kapasitesi 2’dir. İlk iki gönderim bloklanmaz; çünkü tamponda yer vardır. Ancak üçüncü bir gönderim yapılsaydı ve kimse okumuyorsa program beklemeye başlardı. Bu noktada kanal tasarımı önem kazanır: tampon, performans için faydalıdır ama yanlış kullanılırsa hatayı sadece biraz geciktiren yumuşak bir yastığa dönüşebilir.</p>

<p>Birden fazla kanalı dinlemek için Go’nun eğlenceli kontrol kulesi <code class="language-plaintext highlighter-rouge">select</code> kullanılır:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="p">(</span>
    <span class="s">"fmt"</span>
    <span class="s">"time"</span>
<span class="p">)</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">hizli</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="kt">string</span><span class="p">)</span>
    <span class="n">yavas</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="k">chan</span> <span class="kt">string</span><span class="p">)</span>

    <span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">500</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Millisecond</span><span class="p">)</span>
        <span class="n">hizli</span> <span class="o">&lt;-</span> <span class="s">"hızlı veri geldi"</span>
    <span class="p">}()</span>

    <span class="k">go</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
        <span class="n">time</span><span class="o">.</span><span class="n">Sleep</span><span class="p">(</span><span class="m">1</span> <span class="o">*</span> <span class="n">time</span><span class="o">.</span><span class="n">Second</span><span class="p">)</span>
        <span class="n">yavas</span> <span class="o">&lt;-</span> <span class="s">"yavaş veri geldi"</span>
    <span class="p">}()</span>

    <span class="k">for</span> <span class="n">i</span> <span class="o">:=</span> <span class="m">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="m">2</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span> <span class="p">{</span>
        <span class="k">select</span> <span class="p">{</span>
        <span class="k">case</span> <span class="n">msg</span> <span class="o">:=</span> <span class="o">&lt;-</span><span class="n">hizli</span><span class="o">:</span>
            <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
        <span class="k">case</span> <span class="n">msg</span> <span class="o">:=</span> <span class="o">&lt;-</span><span class="n">yavas</span><span class="o">:</span>
            <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">select</code>, hazır olan kanal işlemini seçer. Bu yapı özellikle timeout, iptal sinyali ve fan-in/fan-out desenlerinde çok kullanışlıdır. Örneğin bir işi sonsuza kadar beklemek yerine <code class="language-plaintext highlighter-rouge">time.After</code> ile süre sınırı koyabilirsin.</p>

<table>
  <thead>
    <tr>
      <th>Kanal türü</th>
      <th>Davranış</th>
      <th>Ne zaman kullanılır?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Unbuffered</td>
      <td>Gönderici ve alıcı eşleşene kadar bekler</td>
      <td>Sıkı senkronizasyon gerektiğinde</td>
    </tr>
    <tr>
      <td>Buffered</td>
      <td>Kapasite dolana kadar gönderim beklemez</td>
      <td>Üretici-tüketici hız farkı varsa</td>
    </tr>
    <tr>
      <td>Receive-only</td>
      <td>Sadece okuma yapılır</td>
      <td>API güvenliği için</td>
    </tr>
    <tr>
      <td>Send-only</td>
      <td>Sadece yazma yapılır</td>
      <td>Sorumluluğu sınırlamak için</td>
    </tr>
  </tbody>
</table>

<p>Kanallar güçlüdür ama sihirli değnek değildir. Alıcısı olmayan kanala veri göndermek, göndericisi olmayan kanaldan okumak veya hiç kapanmayan kanalı <code class="language-plaintext highlighter-rouge">range</code> ile tüketmek deadlock’a yol açabilir. Kanalı kapatmak için <code class="language-plaintext highlighter-rouge">close(ch)</code> kullanılır; fakat kural basittir: Genellikle kanalı gönderen taraf kapatır, alan taraf değil.</p>

<p>Sonuç olarak Go kanalları, eşzamanlı programlamayı daha okunabilir bir hikâyeye çevirir. Mutex ile “bu veriye kim dokunuyor?” diye düşünürken, kanallarla “bu veri kime gidiyor?” diye sorarsın. Bu bakış açısı özellikle karmaşık sistemlerde zihinsel yükü azaltır. Goroutine’ler mini karakterlerse, kanallar onların telsiz hattıdır; doğru frekansı ayarlarsan ekip uyum içinde çalışır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="go" /><category term="goroutine" /><category term="channels" /><category term="senkronizasyon" /><summary type="html"><![CDATA[Go dünyasında goroutine’ler sahneye çıktığında ortalık bir anda kalabalıklaşır: aynı anda çalışan fonksiyonlar, paralel iş akışları ve bolca hız! Fakat hızın yanında klasik bir soru gelir: Bu çalışan parçalar birbirleriyle nasıl güvenli konuşacak? Go’nun cevabı nettir: Belleği paylaşarak iletişim kurma; iletişim kurarak belleği paylaş.]]></summary></entry><entry><title type="html">Go’da Metotlar ve Receiver Mantığı: Struct’lara Davranış Kazandırmak</title><link href="https://sonsuzus.github.io/posts/goda-metotlar-ve-receiver-mantigi-structlara-davranis-kazandirmak/" rel="alternate" type="text/html" title="Go’da Metotlar ve Receiver Mantığı: Struct’lara Davranış Kazandırmak" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/goda-metotlar-ve-receiver-mantigi-structlara-davranis-kazandirmak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/goda-metotlar-ve-receiver-mantigi-structlara-davranis-kazandirmak/"><![CDATA[<p>Go’da bir <code class="language-plaintext highlighter-rouge">struct</code> yalnızca veri taşımak zorunda değildir; ona metotlar bağlayarak belirli davranışlar kazandırabiliriz. Bu yaklaşım, klasik sınıf tabanlı nesne yönelimli programlamadan farklıdır: Go’da <code class="language-plaintext highlighter-rouge">class</code>, kalıtım veya <code class="language-plaintext highlighter-rouge">this</code> yoktur; bunun yerine sade, açık ve güçlü bir <code class="language-plaintext highlighter-rouge">receiver</code> mantığı vardır.
``</p>

<p>Go’da metot, teknik olarak bir fonksiyondur; fakat özel bir parametreye sahiptir: <strong>receiver</strong>. Receiver, metodun hangi tipe aitmiş gibi çağrılacağını belirler. Matematiksel olarak düşünürsek, normal bir fonksiyon şöyle modellenebilir: $f(x) \rightarrow y$. Metotta ise fonksiyon, belirli bir veri tipinin bağlamında çalışır: $T.f(x) \rightarrow y$. Buradaki $T$, örneğin bir <code class="language-plaintext highlighter-rouge">User</code>, <code class="language-plaintext highlighter-rouge">Account</code> veya <code class="language-plaintext highlighter-rouge">Rectangle</code> struct’ı olabilir.</p>

<p>Basit bir örnekle başlayalım:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="n">main</span>

<span class="k">import</span> <span class="s">"fmt"</span>

<span class="k">type</span> <span class="n">Rectangle</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">Width</span>  <span class="kt">float64</span>
    <span class="n">Height</span> <span class="kt">float64</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">r</span> <span class="n">Rectangle</span><span class="p">)</span> <span class="n">Area</span><span class="p">()</span> <span class="kt">float64</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">r</span><span class="o">.</span><span class="n">Width</span> <span class="o">*</span> <span class="n">r</span><span class="o">.</span><span class="n">Height</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">box</span> <span class="o">:=</span> <span class="n">Rectangle</span><span class="p">{</span><span class="n">Width</span><span class="o">:</span> <span class="m">10</span><span class="p">,</span> <span class="n">Height</span><span class="o">:</span> <span class="m">5</span><span class="p">}</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">box</span><span class="o">.</span><span class="n">Area</span><span class="p">())</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">(r Rectangle)</code> kısmı receiver’dır. Yani <code class="language-plaintext highlighter-rouge">Area</code> metodu, <code class="language-plaintext highlighter-rouge">Rectangle</code> tipine bağlanmıştır. Artık <code class="language-plaintext highlighter-rouge">Area(box)</code> yazmak yerine daha doğal bir şekilde <code class="language-plaintext highlighter-rouge">box.Area()</code> yazarız. Kodun okunabilirliği artar; çünkü davranış, ilgili veri yapısının yanında durur.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Örnek</th>
      <th>Okunabilirlik</th>
      <th>Go’daki Yeri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Normal fonksiyon</td>
      <td><code class="language-plaintext highlighter-rouge">Area(rect)</code></td>
      <td>Orta</td>
      <td>Geçerli ve sık kullanılır</td>
    </tr>
    <tr>
      <td>Metot</td>
      <td><code class="language-plaintext highlighter-rouge">rect.Area()</code></td>
      <td>Yüksek</td>
      <td>Struct davranışları için idealdir</td>
    </tr>
    <tr>
      <td>Class metodu</td>
      <td><code class="language-plaintext highlighter-rouge">rect.area()</code></td>
      <td>Dile bağlı</td>
      <td>Go’da class yoktur</td>
    </tr>
  </tbody>
</table>

<p>Receiver iki şekilde tanımlanabilir: <strong>value receiver</strong> ve <strong>pointer receiver</strong>. Value receiver, struct’ın bir kopyası üzerinde çalışır. Pointer receiver ise orijinal veriye erişir ve onu değiştirebilir.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Account</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">Owner</span>   <span class="kt">string</span>
    <span class="n">Balance</span> <span class="kt">float64</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">a</span> <span class="n">Account</span><span class="p">)</span> <span class="n">CurrentBalance</span><span class="p">()</span> <span class="kt">float64</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">a</span><span class="o">.</span><span class="n">Balance</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">a</span> <span class="o">*</span><span class="n">Account</span><span class="p">)</span> <span class="n">Deposit</span><span class="p">(</span><span class="n">amount</span> <span class="kt">float64</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="n">amount</span> <span class="o">&lt;=</span> <span class="m">0</span> <span class="p">{</span>
        <span class="k">return</span>
    <span class="p">}</span>
    <span class="n">a</span><span class="o">.</span><span class="n">Balance</span> <span class="o">+=</span> <span class="n">amount</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">CurrentBalance</code> yalnızca okuma yaptığı için value receiver yeterlidir. <code class="language-plaintext highlighter-rouge">Deposit</code> ise bakiyeyi değiştirdiği için pointer receiver kullanır. Eğer para yatırma işlemini formülle ifade edersek: $bakiye_{yeni} = bakiye_{eski} + miktar$. Bu işlemde eski değerin gerçekten güncellenmesi gerekir; kopya üzerinde çalışmak işe yaramaz.</p>

<table>
  <thead>
    <tr>
      <th>Receiver Türü</th>
      <th>Tanım</th>
      <th>Veriyi Değiştirir mi?</th>
      <th>Ne Zaman Kullanılır?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Value receiver</td>
      <td><code class="language-plaintext highlighter-rouge">(a Account)</code></td>
      <td>Hayır, kopya üzerinde çalışır</td>
      <td>Küçük struct’lar, salt okuma işlemleri</td>
    </tr>
    <tr>
      <td>Pointer receiver</td>
      <td><code class="language-plaintext highlighter-rouge">(a *Account)</code></td>
      <td>Evet, orijinali değiştirebilir</td>
      <td>Güncelleme, büyük struct, performans</td>
    </tr>
  </tbody>
</table>

<p>Go’nun burada sunduğu güzellik şudur: Nesne yönelimli programlamadaki “nesne davranış taşır” fikrini alır, ama sınıf hiyerarşisi karmaşasını dayatmaz. Bir struct veri modelini temsil eder, metotlar ise bu veri modeline ait davranışları ifade eder. Yani Go şunu der: “Veriyi ayrı düşün, davranışı açıkça bağla.”</p>

<p>Klasik OOP ile Go yaklaşımını karşılaştıralım:</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Klasik OOP</th>
      <th>Go Yaklaşımı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sınıf</td>
      <td>Temel yapı taşıdır</td>
      <td>Yoktur</td>
    </tr>
    <tr>
      <td>Nesne</td>
      <td>Class örneğidir</td>
      <td>Struct değeri olabilir</td>
    </tr>
    <tr>
      <td>Metot</td>
      <td>Class içinde tanımlanır</td>
      <td>Herhangi bir tipe receiver ile bağlanır</td>
    </tr>
    <tr>
      <td>Kalıtım</td>
      <td>Sınıflar arası aktarım</td>
      <td>Composition tercih edilir</td>
    </tr>
    <tr>
      <td>Polymorphism</td>
      <td>Inheritance veya interface</td>
      <td>Interface ile örtük uygulanır</td>
    </tr>
  </tbody>
</table>

<p>Receiver adı genellikle kısa seçilir: <code class="language-plaintext highlighter-rouge">u User</code>, <code class="language-plaintext highlighter-rouge">r Rectangle</code>, <code class="language-plaintext highlighter-rouge">a Account</code> gibi. Go topluluğu <code class="language-plaintext highlighter-rouge">this</code> veya <code class="language-plaintext highlighter-rouge">self</code> benzeri isimler kullanmayı önermez. Çünkü receiver zaten bağlamı açıkça gösterir. Ayrıca aynı tipe ait metotlarda receiver adını tutarlı seçmek kodun ritmini güzelleştirir.</p>

<p>Biraz daha gerçekçi örnek düşünelim:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Task</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">Title</span>     <span class="kt">string</span>
    <span class="n">Completed</span> <span class="kt">bool</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">t</span> <span class="o">*</span><span class="n">Task</span><span class="p">)</span> <span class="n">Complete</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">t</span><span class="o">.</span><span class="n">Completed</span> <span class="o">=</span> <span class="no">true</span>
<span class="p">}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">t</span> <span class="n">Task</span><span class="p">)</span> <span class="n">Status</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">Completed</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s">"tamamlandı"</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="s">"bekliyor"</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu örnekte <code class="language-plaintext highlighter-rouge">Task</code>, sadece iki alanlı basit bir veri yapısıdır. Ancak <code class="language-plaintext highlighter-rouge">Complete</code> ve <code class="language-plaintext highlighter-rouge">Status</code> metotlarıyla birlikte artık küçük bir davranış modeline dönüşür. Kod başka bir yerde <code class="language-plaintext highlighter-rouge">task.Complete()</code> gördüğünde niyet hemen anlaşılır: görev tamamlanıyor.</p>

<p>Sonuç olarak Go’daki metot ve receiver sistemi, nesne yönelimli düşüncenin pratik tarafını korur: veriyle ilişkili davranışları bir araya getirir. Fakat bunu sınıf, kalıtım ve karmaşık hiyerarşiler olmadan yapar. Eğer bir struct’ın “ne olduğunu” alanları belirliyorsa, “ne yapabildiğini” de metotları belirler. Go’nun felsefesi de tam burada parlar: az sihir, çok netlik.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="golang" /><category term="methods" /><category term="struct" /><category term="receiver" /><category term="nesne-yönelimli-programlama" /><summary type="html"><![CDATA[Go’da bir struct yalnızca veri taşımak zorunda değildir; ona metotlar bağlayarak belirli davranışlar kazandırabiliriz. Bu yaklaşım, klasik sınıf tabanlı nesne yönelimli programlamadan farklıdır: Go’da class, kalıtım veya this yoktur; bunun yerine sade, açık ve güçlü bir receiver mantığı vardır.]]></summary></entry><entry><title type="html">Haritalar (Maps) ile Anahtar-Değer Eşleşmesi</title><link href="https://sonsuzus.github.io/posts/haritalar-maps-ile-anahtar-deger-eslesmesi/" rel="alternate" type="text/html" title="Haritalar (Maps) ile Anahtar-Değer Eşleşmesi" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/haritalar-maps-ile-anahtar-deger-eslesmesi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/haritalar-maps-ile-anahtar-deger-eslesmesi/"><![CDATA[<p>Bir veri koleksiyonunu düşün: Elinde bir öğrenci listesi var ama öğrencileri 0, 1, 2 gibi indekslerle değil, okul numarası, e-posta adresi veya kullanıcı adı gibi anlamlı anahtarlarla bulmak istiyorsun. İşte haritalar, yani Maps, tam bu noktada sahneye çıkar. Map yapısı, veriyi anahtar-değer çifti olarak saklar ve arama, ekleme, silme gibi işlemleri oldukça okunabilir hale getirir.
``</p>

<h2 id="map-mantığı-nedir">Map Mantığı Nedir?</h2>

<p>Map, temel olarak şu fikre dayanır: Her değerin bir anahtarı vardır. Matematiksel olarak bunu bir eşleme fonksiyonu gibi düşünebiliriz:</p>

<p>$f: K \rightarrow V$</p>

<p>Burada $K$ anahtarlar kümesini, $V$ ise değerler kümesini temsil eder. Örneğin bir kullanıcı sisteminde <code class="language-plaintext highlighter-rouge">kullaniciAdi -&gt; profilBilgisi</code> şeklinde bir ilişki kurabiliriz.</p>

<p>Dizilerde verilere genellikle indeksle ulaşırız:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">renkler</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">kirmizi</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">mavi</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">yesil</span><span class="dl">'</span><span class="p">];</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">renkler</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> <span class="c1">// mavi</span>
</code></pre></div></div>

<p>Ama indeksler her zaman anlamlı değildir. <code class="language-plaintext highlighter-rouge">renkler[1]</code> ifadesi çalışır, fakat 1 sayısı bize iş kuralı hakkında pek bir şey söylemez. Map ile anahtarları kendimiz belirleyebiliriz.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">renkKodlari</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Map</span><span class="p">();</span>
<span class="nx">renkKodlari</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">hata</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">kirmizi</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">renkKodlari</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">basari</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">yesil</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">renkKodlari</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">uyari</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">sari</span><span class="dl">'</span><span class="p">);</span>

<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">renkKodlari</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">basari</span><span class="dl">'</span><span class="p">));</span> <span class="c1">// yesil</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">basari</code> anahtarı, <code class="language-plaintext highlighter-rouge">yesil</code> değerine karşılık gelir. Kod artık yalnızca çalışmakla kalmaz, aynı zamanda hikâye anlatır.</p>

<h2 id="dizi-nesne-ve-map-karşılaştırması">Dizi, Nesne ve Map Karşılaştırması</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Dizi</th>
      <th>Nesne</th>
      <th>Map</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Anahtar tipi</td>
      <td>Sayısal indeks</td>
      <td>Genellikle string/symbol</td>
      <td>Her tür olabilir</td>
    </tr>
    <tr>
      <td>Sıralama</td>
      <td>İndekse bağlı</td>
      <td>Kurallara bağlı</td>
      <td>Ekleme sırası korunur</td>
    </tr>
    <tr>
      <td>Boyut öğrenme</td>
      <td><code class="language-plaintext highlighter-rouge">length</code></td>
      <td>Ek işlem gerekir</td>
      <td><code class="language-plaintext highlighter-rouge">size</code></td>
    </tr>
    <tr>
      <td>Sık kullanım</td>
      <td>Sıralı listeler</td>
      <td>Basit kayıtlar</td>
      <td>Dinamik anahtar-değer koleksiyonları</td>
    </tr>
    <tr>
      <td>Silme işlemi</td>
      <td><code class="language-plaintext highlighter-rouge">splice</code> vb.</td>
      <td><code class="language-plaintext highlighter-rouge">delete</code></td>
      <td><code class="language-plaintext highlighter-rouge">delete</code> metodu</td>
    </tr>
  </tbody>
</table>

<p>Map yapısının güzel tarafı, anahtar olarak yalnızca string değil, nesne, fonksiyon hatta başka bir Map bile kullanabilmesidir. Bu, özellikle cache, kullanıcı oturumu, ayar yönetimi ve oyun içi envanter gibi senaryolarda çok işe yarar.</p>

<h2 id="temel-i̇şlemler-ekleme-arama-silme">Temel İşlemler: Ekleme, Arama, Silme</h2>

<p>Bir Map üzerinde en sık kullanılan işlemler şunlardır:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">sepet</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Map</span><span class="p">();</span>

<span class="c1">// Ekleme veya güncelleme</span>
<span class="nx">sepet</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">elma</span><span class="dl">'</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
<span class="nx">sepet</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">muz</span><span class="dl">'</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
<span class="nx">sepet</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">elma</span><span class="dl">'</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span> <span class="c1">// elma miktarı güncellendi</span>

<span class="c1">// Arama</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">sepet</span><span class="p">.</span><span class="nf">has</span><span class="p">(</span><span class="dl">'</span><span class="s1">muz</span><span class="dl">'</span><span class="p">));</span> <span class="c1">// true</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">sepet</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">elma</span><span class="dl">'</span><span class="p">));</span> <span class="c1">// 4</span>

<span class="c1">// Silme</span>
<span class="nx">sepet</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="dl">'</span><span class="s1">muz</span><span class="dl">'</span><span class="p">);</span>

<span class="c1">// Boyut</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">sepet</span><span class="p">.</span><span class="nx">size</span><span class="p">);</span> <span class="c1">// 1</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">set</code> metodu hem yeni kayıt ekler hem de aynı anahtar varsa değeri günceller. <code class="language-plaintext highlighter-rouge">get</code> değeri getirir, <code class="language-plaintext highlighter-rouge">has</code> anahtarın varlığını kontrol eder, <code class="language-plaintext highlighter-rouge">delete</code> ise eşleşmeyi kaldırır.</p>

<h2 id="performans-açısından-neden-önemli">Performans Açısından Neden Önemli?</h2>

<p>Map yapıları çoğu programlama dilinde hash table benzeri bir altyapıyla uygulanır. Bu nedenle ortalama durumda arama, ekleme ve silme işlemleri yaklaşık olarak $O(1)$ karmaşıklığındadır. Yani koleksiyon büyüse bile işlem süresi genellikle dramatik biçimde artmaz.</p>

<p>Elbette bu teorik bir ortalamadır. Kötü hash dağılımı gibi özel durumlarda maliyet artabilir. Ancak pratikte Map, özellikle sık arama yapılan yapılarda diziye göre daha uygun olabilir. Bir dizide elemanı bulmak için tek tek dolaşmak gerekirse maliyet $O(n)$ olur.</p>

<table>
  <thead>
    <tr>
      <th>İşlem</th>
      <th>Dizi ile yaklaşım</th>
      <th>Map ile yaklaşım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kullanıcıyı ID ile bulma</td>
      <td>Tüm listeyi gezmek gerekebilir</td>
      <td><code class="language-plaintext highlighter-rouge">get(id)</code></td>
    </tr>
    <tr>
      <td>Kayıt var mı kontrolü</td>
      <td><code class="language-plaintext highlighter-rouge">find</code> veya <code class="language-plaintext highlighter-rouge">some</code></td>
      <td><code class="language-plaintext highlighter-rouge">has(key)</code></td>
    </tr>
    <tr>
      <td>Kayıt silme</td>
      <td>İndeksi bul, sonra sil</td>
      <td><code class="language-plaintext highlighter-rouge">delete(key)</code></td>
    </tr>
  </tbody>
</table>

<h2 id="küçük-bir-örnek-kullanıcı-oturumları">Küçük Bir Örnek: Kullanıcı Oturumları</h2>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">oturumlar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Map</span><span class="p">();</span>

<span class="kd">function</span> <span class="nf">oturumAc</span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">kullanici</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">oturumlar</span><span class="p">.</span><span class="nf">set</span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">ad</span><span class="p">:</span> <span class="nx">kullanici</span><span class="p">,</span>
    <span class="na">baslangic</span><span class="p">:</span> <span class="nb">Date</span><span class="p">.</span><span class="nf">now</span><span class="p">()</span>
  <span class="p">});</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nf">oturumKontrol</span><span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">if </span><span class="p">(</span><span class="o">!</span><span class="nx">oturumlar</span><span class="p">.</span><span class="nf">has</span><span class="p">(</span><span class="nx">token</span><span class="p">))</span> <span class="p">{</span>
    <span class="k">return</span> <span class="dl">'</span><span class="s1">Oturum bulunamadi</span><span class="dl">'</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="kd">const</span> <span class="nx">oturum</span> <span class="o">=</span> <span class="nx">oturumlar</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="nx">token</span><span class="p">);</span>
  <span class="k">return</span> <span class="s2">`</span><span class="p">${</span><span class="nx">oturum</span><span class="p">.</span><span class="nx">ad</span><span class="p">}</span><span class="s2"> aktif`</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span> <span class="nf">oturumKapat</span><span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">return</span> <span class="nx">oturumlar</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">token</span><span class="p">);</span>
<span class="p">}</span>

<span class="nf">oturumAc</span><span class="p">(</span><span class="dl">'</span><span class="s1">abc123</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Ada</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nf">oturumKontrol</span><span class="p">(</span><span class="dl">'</span><span class="s1">abc123</span><span class="dl">'</span><span class="p">));</span>
<span class="nf">oturumKapat</span><span class="p">(</span><span class="dl">'</span><span class="s1">abc123</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>

<p>Bu örnekte token anahtar, kullanıcı oturum bilgisi ise değerdir. Böylece her oturuma hızlıca erişebiliriz.</p>

<h2 id="ne-zaman-map-kullanmalı">Ne Zaman Map Kullanmalı?</h2>

<p>Eğer verilerin doğal bir anahtarı varsa, sık sık arama yapıyorsan veya anahtarların string dışında türler olmasını istiyorsan Map iyi bir seçimdir. Sadece sıralı bir liste tutuyorsan dizi daha uygundur. Sabit yapılı bir veri modeli için ise nesne veya sınıf daha okunabilir olabilir.</p>

<p>Kısacası Map, veriye anlamlı bir kapı etiketi takmaktır. İndekslerin soğuk apartman numaralarından sıkıldıysan, anahtar-değer dünyasına hoş geldin!</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="map" /><category term="veri-yapilari" /><category term="javascript" /><summary type="html"><![CDATA[Bir veri koleksiyonunu düşün: Elinde bir öğrenci listesi var ama öğrencileri 0, 1, 2 gibi indekslerle değil, okul numarası, e-posta adresi veya kullanıcı adı gibi anlamlı anahtarlarla bulmak istiyorsun. İşte haritalar, yani Maps, tam bu noktada sahneye çıkar. Map yapısı, veriyi anahtar-değer çifti olarak saklar ve arama, ekleme, silme gibi işlemleri oldukça okunabilir hale getirir.]]></summary></entry><entry><title type="html">Hata Yönetimi: Error Değerleri ve Panic-Recover ile Kontrollü Kaos</title><link href="https://sonsuzus.github.io/posts/hata-yonetimi-error-degerleri-ve-panic-recover-ile-kontrollu-kaos/" rel="alternate" type="text/html" title="Hata Yönetimi: Error Değerleri ve Panic-Recover ile Kontrollü Kaos" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/hata-yonetimi-error-degerleri-ve-panic-recover-ile-kontrollu-kaos</id><content type="html" xml:base="https://sonsuzus.github.io/posts/hata-yonetimi-error-degerleri-ve-panic-recover-ile-kontrollu-kaos/"><![CDATA[<p>Bir programın gerçek dünyayla ilk teması genellikle bir hatadır: dosya yoktur, ağ isteği zaman aşımına uğrar, kullanıcı sayı yerine “patates” yazar. Bazı diller bu anlarda istisna fırlatıp akışı dramatik biçimde keserken, Go gibi yaklaşımlar hatayı sıradan bir değer olarak masaya koyar. Yani hata, programın çökmesine çalışan bir canavar değil; kontrol edilmesi gereken bir dönüş değeridir.
``</p>

<h2 id="hata-bir-olay-değil-bir-değerdir">Hata bir olay değil, bir değerdir</h2>

<p>Go’nun hata yönetimi felsefesi basittir: Fonksiyonlar başarılı sonucu ve hata bilgisini birlikte döndürebilir. Tipik imza şuna benzer:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">Oku</span><span class="p">(</span><span class="n">path</span> <span class="kt">string</span><span class="p">)</span> <span class="p">([]</span><span class="kt">byte</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">data</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">os</span><span class="o">.</span><span class="n">ReadFile</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
        <span class="k">return</span> <span class="no">nil</span><span class="p">,</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"dosya okunamadı: %w"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">data</span><span class="p">,</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">error</code>, özel bir büyü değil; <code class="language-plaintext highlighter-rouge">Error() string</code> metoduna sahip bir arayüzdür. Matematiksel düşünürsek fonksiyon sonucu şöyle modellenebilir: $(T, E)$; burada $T$ beklenen veri, $E$ ise hata durumudur. Başarı halinde $E = nil$, hata halinde çoğu zaman $T$ kullanılmaz. Akış şu denklemle okunabilir: $P(başarı) + P(hata) = 1$. Yani fonksiyon ya düzgün sonuç üretir ya da neden üretemediğini açıkça bildirir.</p>

<h2 id="i̇stisna-mı-değer-mi">İstisna mı, değer mi?</h2>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Akış Kontrolü</th>
      <th>Okunabilirlik</th>
      <th>Risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Exception</td>
      <td>Akış aniden başka bloğa zıplar</td>
      <td>Kısa ama gizli yollar içerir</td>
      <td>Yakalanmazsa çökme</td>
    </tr>
    <tr>
      <td>Error value</td>
      <td>Hata açıkça kontrol edilir</td>
      <td>Daha fazla satır ama netlik yüksek</td>
      <td>Kontrol unutulursa mantık hatası</td>
    </tr>
    <tr>
      <td>Panic</td>
      <td>Normal akışı durdurur</td>
      <td>Acil durumlar için belirgin</td>
      <td>Yanlış kullanımda sert çöküş</td>
    </tr>
  </tbody>
</table>

<p>Bu tablo Go’nun neden “hata varsa söyle, saklama” dediğini gösterir. Kod biraz daha uzun görünür; evet, <code class="language-plaintext highlighter-rouge">if err != nil</code> satırları çoğalır. Ama karşılığında fonksiyonun başarısız olabileceği yerler neon tabela gibi görünür.</p>

<h2 id="error-wrapping-hatanın-dedikodu-zinciri">Error wrapping: Hatanın dedikodu zinciri</h2>

<p>Hata mesajını sadece “olmadı” diye döndürmek, kullanıcıya “bir şeyler ters gitti” demek gibidir; doğru ama pek faydalı değildir. Go’da <code class="language-plaintext highlighter-rouge">%w</code> ile hata sarmalanabilir:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">AyarYukle</span><span class="p">()</span> <span class="kt">error</span> <span class="p">{</span>
    <span class="n">err</span> <span class="o">:=</span> <span class="n">VeritabaniBaglan</span><span class="p">()</span>
    <span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">fmt</span><span class="o">.</span><span class="n">Errorf</span><span class="p">(</span><span class="s">"ayar yükleme başarısız: %w"</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu sayede üst katman hem bağlamı görür hem de <code class="language-plaintext highlighter-rouge">errors.Is</code> veya <code class="language-plaintext highlighter-rouge">errors.As</code> ile kök hatayı inceleyebilir. Böylece hata, apartman dedikodusu gibi kat kat dolaşır ama kimden çıktığı da bellidir.</p>

<h2 id="peki-panic-ne-zaman">Peki panic ne zaman?</h2>

<p><code class="language-plaintext highlighter-rouge">panic</code>, “bu fonksiyon beklenen bir hata yaşadı” demek değildir. Daha çok “programın varsayımları çöktü” anlamına gelir. Örneğin imkânsız olması gereken bir durum gerçekleştiyse, başlatma sırasında kritik yapılandırma yoksa veya bellek dışı tutarsızlık oluştuysa kullanılabilir.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th>Tercih</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kullanıcı yanlış dosya yolu verdi</td>
      <td><code class="language-plaintext highlighter-rouge">error</code> döndür</td>
    </tr>
    <tr>
      <td>API isteği timeout oldu</td>
      <td><code class="language-plaintext highlighter-rouge">error</code> döndür</td>
    </tr>
    <tr>
      <td>Program başlarken zorunlu config yok</td>
      <td>Duruma göre <code class="language-plaintext highlighter-rouge">panic</code> veya fatal log</td>
    </tr>
    <tr>
      <td>Kodun asla ulaşmaması gereken dalı çalıştı</td>
      <td><code class="language-plaintext highlighter-rouge">panic</code> makul olabilir</td>
    </tr>
  </tbody>
</table>

<h2 id="recover-panik-odasının-yangın-çıkışı">Recover: Panik odasının yangın çıkışı</h2>

<p><code class="language-plaintext highlighter-rouge">recover</code>, yalnızca <code class="language-plaintext highlighter-rouge">defer</code> içinde çağrıldığında aktif bir <code class="language-plaintext highlighter-rouge">panic</code>i yakalayabilir. Bu mekanizma exception yakalamaya benzese de Go’da günlük hata yönetimi için önerilmez; daha çok sınır katmanlarında, örneğin HTTP sunucusunda tek bir isteğin tüm sistemi devirmesini engellemek için kullanılır.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">GuvenliCalistir</span><span class="p">(</span><span class="n">fn</span> <span class="k">func</span><span class="p">())</span> <span class="p">{</span>
    <span class="k">defer</span> <span class="k">func</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">if</span> <span class="n">r</span> <span class="o">:=</span> <span class="nb">recover</span><span class="p">();</span> <span class="n">r</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
            <span class="n">log</span><span class="o">.</span><span class="n">Printf</span><span class="p">(</span><span class="s">"panic yakalandı: %v"</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}()</span>

    <span class="n">fn</span><span class="p">()</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kod, verilen fonksiyonu çalıştırır; içeride <code class="language-plaintext highlighter-rouge">panic</code> olursa program tamamen yere kapaklanmadan önce durumu loglar. Ancak dikkat: <code class="language-plaintext highlighter-rouge">recover</code> hatayı yok etmez, sadece kontrolü geri verir. Verinin tutarlı olup olmadığını hâlâ sen düşünmelisin.</p>

<h2 id="pratik-tasarım-önerileri">Pratik tasarım önerileri</h2>

<ol>
  <li>Beklenen başarısızlıkları <code class="language-plaintext highlighter-rouge">error</code> olarak döndür.</li>
  <li>Hatalara bağlam ekle: “bağlanamadı” yerine “kullanıcı profili yüklenirken veritabanına bağlanılamadı” daha değerlidir.</li>
  <li><code class="language-plaintext highlighter-rouge">panic</code>i kontrol akışı için kullanma; <code class="language-plaintext highlighter-rouge">if err != nil</code> sıkıcı olabilir ama güvenilirdir.</li>
  <li><code class="language-plaintext highlighter-rouge">recover</code>i uygulama sınırlarında kullan: HTTP middleware, worker supervisor, CLI komut sarmalayıcıları gibi.</li>
</ol>

<p>Sonuç olarak Go’nun hata yönetimi şunu öğretir: Hata, utanılacak bir istisna değil, sistemin konuşma biçimidir. Onu değer olarak döndürdüğünde programın daha tahmin edilebilir, test edilebilir ve bakım yapılabilir olur. <code class="language-plaintext highlighter-rouge">panic</code> ise sahneye nadiren çıkan duman makinesi gibidir; doğru anda dramatik, yanlış anda tüm gösteriyi mahveder.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="go" /><category term="hata-yönetimi" /><category term="panic-recover" /><summary type="html"><![CDATA[Bir programın gerçek dünyayla ilk teması genellikle bir hatadır: dosya yoktur, ağ isteği zaman aşımına uğrar, kullanıcı sayı yerine “patates” yazar. Bazı diller bu anlarda istisna fırlatıp akışı dramatik biçimde keserken, Go gibi yaklaşımlar hatayı sıradan bir değer olarak masaya koyar. Yani hata, programın çökmesine çalışan bir canavar değil; kontrol edilmesi gereken bir dönüş değeridir.]]></summary></entry><entry><title type="html">Yapılar (Structs) ve Veri Odaklı Tasarım: Veriyi Kahraman Yapmak</title><link href="https://sonsuzus.github.io/posts/yapilar-structs-ve-veri-odakli-tasarim-veriyi-kahraman-yapmak/" rel="alternate" type="text/html" title="Yapılar (Structs) ve Veri Odaklı Tasarım: Veriyi Kahraman Yapmak" /><published>2026-07-24T00:00:00+00:00</published><updated>2026-07-24T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/yapilar-structs-ve-veri-odakli-tasarim-veriyi-kahraman-yapmak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/yapilar-structs-ve-veri-odakli-tasarim-veriyi-kahraman-yapmak/"><![CDATA[<p>Programlamada bazen bir şeyi nesne gibi davranışlarıyla değil, taşıdığı verilerle düşünmek daha doğrudur. İşte yapılar, yani structs, tam bu noktada sahneye çıkar. Bir koordinat, renk, sağlık değeri, tarih aralığı veya fiziksel hız vektörü düşünün: Bunlar genellikle küçük, anlamlı ve birlikte taşınması gereken veri paketleridir. Struct, farklı tiplerdeki alanları mantıksal bir bütün halinde gruplar ve özellikle veri odaklı tasarımda gereksiz soyutlama sisini dağıtarak işlemciye daha dost bir programlama modeli sunar.
``</p>

<h2 id="struct-nedir">Struct nedir?</h2>

<p>Struct, birden fazla veriyi tek bir özel tip altında toplamanızı sağlayan bir yapıdır. Sınıfa benzer görünür; alanları, metotları ve özellikleri olabilir. Ancak birçok dilde struct kavramsal olarak daha hafif, daha doğrudan ve veri merkezlidir. Özellikle C, C++, C# ve Rust gibi dillerde struct, bellekteki verinin düzenini anlamak açısından çok önemlidir.</p>

<p>Basit bir örnekle başlayalım:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">struct</span> <span class="nc">Health</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">Current</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">Maximum</span><span class="p">;</span>

    <span class="k">public</span> <span class="kt">float</span> <span class="n">Ratio</span>
    <span class="p">{</span>
        <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="kt">float</span><span class="p">)</span><span class="n">Current</span> <span class="p">/</span> <span class="n">Maximum</span><span class="p">;</span> <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu struct, bir karakterin can bilgisini taşır. <code class="language-plaintext highlighter-rouge">Current</code> ve <code class="language-plaintext highlighter-rouge">Maximum</code> ayrı ayrı değişkenler olabilirdi; fakat birlikte anlamlı oldukları için tek bir tip altında toplanmaları kodu daha okunabilir yapar.</p>

<h2 id="struct-ile-class-arasındaki-temel-farklar">Struct ile class arasındaki temel farklar</h2>

<p>Her dilde ayrıntılar değişebilir ama genel düşünce şudur: class çoğu zaman kimlik ve davranış odaklıdır, struct ise veri odaklıdır.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Struct</th>
      <th>Class</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Ana fikir</td>
      <td>Veri gruplama</td>
      <td>Nesne ve davranış modelleme</td>
    </tr>
    <tr>
      <td>Kullanım alanı</td>
      <td>Küçük, anlamlı veri paketleri</td>
      <td>Karmaşık iş kuralları ve ilişkiler</td>
    </tr>
    <tr>
      <td>Bellek yaklaşımı</td>
      <td>Daha düz ve kompakt olabilir</td>
      <td>Referanslar ve dolaylı erişim yaygındır</td>
    </tr>
    <tr>
      <td>Zihinsel model</td>
      <td>Bu veri ne?</td>
      <td>Bu nesne ne yapar?</td>
    </tr>
  </tbody>
</table>

<p>Örneğin bir oyun motorunda <code class="language-plaintext highlighter-rouge">Position</code>, <code class="language-plaintext highlighter-rouge">Velocity</code>, <code class="language-plaintext highlighter-rouge">Health</code> gibi tipler struct olmaya çok uygundur. Buna karşılık <code class="language-plaintext highlighter-rouge">InventoryManager</code> veya <code class="language-plaintext highlighter-rouge">PaymentService</code> gibi davranış yönü ağır bileşenler class olarak daha anlamlıdır.</p>

<h2 id="veri-odaklı-tasarımın-mantığı">Veri odaklı tasarımın mantığı</h2>

<p>Veri odaklı tasarım, programı önce verinin şekline ve işlenme biçimine göre düşünmektir. Geleneksel nesne yönelimli yaklaşımda sıkça şu soru sorulur: Bu nesnenin hangi metotları var? Veri odaklı yaklaşım ise şunu sorar: Hangi veriyi, hangi sırayla, ne kadar sık işleyeceğim?</p>

<p>Performans açısından kritik nokta bellek erişimidir. Modern işlemciler veriyi tek tek sihirli şekilde değil, cache line denilen bloklarla okur. Basitçe düşünürsek:</p>

<p>$T \approx N \times C_{access}$</p>

<p>Burada $N$ erişilen veri sayısı, $C_{access}$ ise her erişimin maliyetidir. Eğer veriler bellekte dağınıksa $C_{access}$ artar. Veriler ardışık ve kompakt ise işlemci cache daha verimli çalışır.</p>

<table>
  <thead>
    <tr>
      <th>Tasarım</th>
      <th>Veri düzeni</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Nesne odaklı</td>
      <td>Dağınık referanslar olabilir</td>
      <td>Modelleme kolaydır</td>
      <td>Cache kaçırma artabilir</td>
    </tr>
    <tr>
      <td>Veri odaklı</td>
      <td>Ardışık diziler yaygındır</td>
      <td>Yüksek performans</td>
      <td>Başta daha fazla plan ister</td>
    </tr>
  </tbody>
</table>

<h2 id="struct-ile-daha-düzenli-veri-modeli">Struct ile daha düzenli veri modeli</h2>

<p>Diyelim ki çok sayıda karakterin sağlık bilgisini güncelliyoruz:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">struct</span> <span class="nc">PlayerStats</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">Health</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="n">Armor</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="n">Speed</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">ApplyDamage</span><span class="p">(</span><span class="k">ref</span> <span class="n">PlayerStats</span> <span class="n">stats</span><span class="p">,</span> <span class="kt">int</span> <span class="n">damage</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">reduced</span> <span class="p">=</span> <span class="n">damage</span> <span class="p">-</span> <span class="n">stats</span><span class="p">.</span><span class="n">Armor</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">reduced</span> <span class="p">&lt;</span> <span class="m">0</span><span class="p">)</span> <span class="n">reduced</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
    <span class="n">stats</span><span class="p">.</span><span class="n">Health</span> <span class="p">-=</span> <span class="n">reduced</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">PlayerStats</code>, karaktere ait temel sayısal değerleri bir araya getirir. <code class="language-plaintext highlighter-rouge">ApplyDamage</code> fonksiyonu ise struct üzerinde işlem yapar. <code class="language-plaintext highlighter-rouge">ref</code> kullanımı, bazı dillerde veya senaryolarda kopyalama maliyetini azaltmak için tercih edilir. Çünkü struct değer gibi taşındığında kopyalanabilir; küçük structlarda bu harika, büyük structlarda ise dikkat gerektirir.</p>

<h2 id="struct-seçerken-dikkat-edilmesi-gerekenler">Struct seçerken dikkat edilmesi gerekenler</h2>

<p>Struct kullanmak her derde deva değildir. Küçük ve değişmez veri tiplerinde çok güçlüdür; fakat devasa veri paketleri oluşturursanız kopyalama maliyeti can sıkabilir. Pratik bir sezgi olarak, struct veri taşımalı; karmaşık yaşam döngüsü, miras hiyerarşisi veya yoğun davranış gerekiyorsa class düşünülmelidir.</p>

<table>
  <thead>
    <tr>
      <th>Durum</th>
      <th style="text-align: right">Struct iyi fikir mi?</th>
      <th>Neden</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>2D nokta, renk, para miktarı</td>
      <td style="text-align: right">Evet</td>
      <td>Küçük ve anlamlı veri</td>
    </tr>
    <tr>
      <td>50 alanlı kullanıcı profili</td>
      <td style="text-align: right">Genelde hayır</td>
      <td>Kopyalama ve karmaşıklık artar</td>
    </tr>
    <tr>
      <td>Oyun bileşen verisi</td>
      <td style="text-align: right">Evet</td>
      <td>Veri odaklı sistemlere uygundur</td>
    </tr>
    <tr>
      <td>Servis sınıfı</td>
      <td style="text-align: right">Hayır</td>
      <td>Davranış ve bağımlılık baskındır</td>
    </tr>
  </tbody>
</table>

<h2 id="sonuç">Sonuç</h2>

<p>Structs, programlamada veriyi ciddiye almanın zarif yollarından biridir. Sınıflar dünyayı nesneler ve davranışlarla anlatırken, structlar küçük veri gerçekliklerini net ve kompakt biçimde ifade eder. Veri odaklı tasarımda amaç, kodu sadece güzel göstermek değil, verinin bellekte nasıl yaşadığını da hesaba katmaktır. Kısacası: Eğer programınız bir mutfaksa, classlar aşçı olabilir; structlar ise düzenli kesilmiş malzemelerdir. Lezzetli ve hızlı yemek için ikisine de ihtiyaç vardır, ama hangi malzemenin nerede durduğunu bilmek oyunu değiştirir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="struct" /><category term="veri-odaklı-tasarım" /><category term="programlama" /><summary type="html"><![CDATA[Programlamada bazen bir şeyi nesne gibi davranışlarıyla değil, taşıdığı verilerle düşünmek daha doğrudur. İşte yapılar, yani structs, tam bu noktada sahneye çıkar. Bir koordinat, renk, sağlık değeri, tarih aralığı veya fiziksel hız vektörü düşünün: Bunlar genellikle küçük, anlamlı ve birlikte taşınması gereken veri paketleridir. Struct, farklı tiplerdeki alanları mantıksal bir bütün halinde gruplar ve özellikle veri odaklı tasarımda gereksiz soyutlama sisini dağıtarak işlemciye daha dost bir programlama modeli sunar.]]></summary></entry><entry><title type="html">ALSA Loopback ile Gerçek Zamanlı Yankı ve Pitch Pedalı Yapımı</title><link href="https://sonsuzus.github.io/posts/alsa-loopback-ile-gercek-zamanli-yanki-ve-pitch-pedali-yapimi/" rel="alternate" type="text/html" title="ALSA Loopback ile Gerçek Zamanlı Yankı ve Pitch Pedalı Yapımı" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/alsa-loopback-ile-gercek-zamanli-yanki-ve-pitch-pedali-yapimi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/alsa-loopback-ile-gercek-zamanli-yanki-ve-pitch-pedali-yapimi/"><![CDATA[<p>Linux üzerinde gitar pedalı gibi çalışan bir ses efekti sistemi kurmak kulağa stüdyo büyüsü gibi gelebilir; ama ALSA’nın loopback cihazı ve biraz DSP bilgisiyle mikrofon girişini yakalayıp yankı ve pitch değişimi uygulayan gerçek zamanlı bir pedal yapmak gayet mümkün. Bu yazıda hedefimiz: mikrofonu sanal bir ses hattına bağlamak, sesi küçük tamponlar halinde işlemek ve çıktıyı hoparlöre ya da başka bir uygulamaya göndermek.
``
ALSA’da loopback cihazı, fiziksel kablo takmadan ses sinyalini bir uygulamadan diğerine taşıyan sanal bir ses kartıdır. <code class="language-plaintext highlighter-rouge">snd-aloop</code> modülü yüklendiğinde sistemde genellikle <code class="language-plaintext highlighter-rouge">Loopback</code> adlı yeni bir kart görünür. Mantık şudur: bir tarafa yazılan ses, diğer taraftan okunabilir. Böylece mikrofon, efekt işlemcisi ve hoparlör arasında dijital bir pedal tahtası kurarız.</p>

<p>Önce modülü etkinleştirelim:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>modprobe snd-aloop
aplay <span class="nt">-l</span>
arecord <span class="nt">-l</span>
</code></pre></div></div>

<p>Kalıcı yapmak için <code class="language-plaintext highlighter-rouge">/etc/modules-load.d/alsa-loopback.conf</code> içine şu satır eklenebilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>snd-aloop
</code></pre></div></div>

<p>Ses zincirimiz teorik olarak şöyle çalışır:</p>

<table>
  <thead>
    <tr>
      <th>Aşama</th>
      <th>Görev</th>
      <th>Gecikmeye Etkisi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Mikrofon girişi</td>
      <td>Analog sesi sayısala çevirir</td>
      <td>Düşük/orta</td>
    </tr>
    <tr>
      <td>ALSA buffer</td>
      <td>Sesi bloklar halinde taşır</td>
      <td>Kritik</td>
    </tr>
    <tr>
      <td>Efekt işlemcisi</td>
      <td>Yankı ve pitch uygular</td>
      <td>CPU’ya bağlı</td>
    </tr>
    <tr>
      <td>Loopback çıkışı</td>
      <td>İşlenmiş sesi yönlendirir</td>
      <td>Düşük</td>
    </tr>
    <tr>
      <td>Hoparlör/uygulama</td>
      <td>Son sesi çalar veya kaydeder</td>
      <td>Değişken</td>
    </tr>
  </tbody>
</table>

<p>Gerçek zamanlı ses işlemede en önemli denklem gecikmedir. Örnekleme frekansı $f_s$ ve tampon boyutu $N$ ise tek tampon gecikmesi yaklaşık şöyledir:</p>

<p>$L = \frac{N}{f_s}$</p>

<p>Örneğin $N=256$ ve $f_s=48000$ için $L \approx 5.3ms$ olur. Bu değer küçükse pedal hızlı tepki verir; ancak çok küçültürsek CPU yetişemez ve çıtırtılar başlar. Yani düşük gecikme ile kararlılık arasında tatlı bir denge ararız.</p>

<p>Yankı efekti temelde gecikmiş sinyalin tekrar karıştırılmasıdır:</p>

<p>$y[n] = x[n] + g \cdot x[n-D]$</p>

<p>Burada $D$ gecikme örneği, $g$ ise geri besleme veya karışım miktarıdır. Pitch değiştirme ise daha hilelidir; sesi hızlandırıp/yavaşlatmak perdeyi değiştirir ama süreyi de bozar. Basit bir pedal prototipinde kısa tamponlar üzerinde yeniden örnekleme kullanabiliriz. Profesyonel sonuç için phase vocoder veya granular yöntemler tercih edilir.</p>

<p>Aşağıdaki Python örneği, <code class="language-plaintext highlighter-rouge">sounddevice</code> ile girişten ses alır, basit yankı ekler ve pitch için yeniden örnekleme tabanlı kaba bir yaklaşım uygular. Üretim ortamında JACK/PipeWire daha esnek olabilir; fakat ALSA mantığını kavramak için bu örnek yeterli bir laboratuvardır.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="n">sounddevice</span> <span class="k">as</span> <span class="n">sd</span>
<span class="kn">from</span> <span class="n">scipy.signal</span> <span class="kn">import</span> <span class="n">resample</span>

<span class="n">fs</span> <span class="o">=</span> <span class="mi">48000</span>
<span class="n">block</span> <span class="o">=</span> <span class="mi">512</span>
<span class="n">delay_ms</span> <span class="o">=</span> <span class="mi">280</span>
<span class="n">delay_samples</span> <span class="o">=</span> <span class="nf">int</span><span class="p">(</span><span class="n">fs</span> <span class="o">*</span> <span class="n">delay_ms</span> <span class="o">/</span> <span class="mi">1000</span><span class="p">)</span>
<span class="n">feedback</span> <span class="o">=</span> <span class="mf">0.35</span>
<span class="n">mix</span> <span class="o">=</span> <span class="mf">0.55</span>
<span class="n">pitch_ratio</span> <span class="o">=</span> <span class="mf">1.12</span>  <span class="c1"># 1.0 normal, &gt;1 tiz, &lt;1 pes
</span>
<span class="n">delay_buffer</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">zeros</span><span class="p">(</span><span class="n">delay_samples</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">np</span><span class="p">.</span><span class="n">float32</span><span class="p">)</span>
<span class="n">write_pos</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">def</span> <span class="nf">pitch_shift_simple</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">ratio</span><span class="p">):</span>
    <span class="c1"># Kısa bloğu yeniden örnekleyerek perdeyi kaba şekilde değiştirir.
</span>    <span class="c1"># Sonra tekrar eski blok boyuna getirir.
</span>    <span class="k">if</span> <span class="n">ratio</span> <span class="o">==</span> <span class="mf">1.0</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">x</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
    <span class="n">stretched</span> <span class="o">=</span> <span class="nf">resample</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="nf">max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nf">int</span><span class="p">(</span><span class="n">n</span> <span class="o">/</span> <span class="n">ratio</span><span class="p">)))</span>
    <span class="n">shifted</span> <span class="o">=</span> <span class="nf">resample</span><span class="p">(</span><span class="n">stretched</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">shifted</span><span class="p">.</span><span class="nf">astype</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">float32</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">indata</span><span class="p">,</span> <span class="n">outdata</span><span class="p">,</span> <span class="n">frames</span><span class="p">,</span> <span class="n">time</span><span class="p">,</span> <span class="n">status</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">write_pos</span><span class="p">,</span> <span class="n">delay_buffer</span>
    <span class="k">if</span> <span class="n">status</span><span class="p">:</span>
        <span class="nf">print</span><span class="p">(</span><span class="n">status</span><span class="p">)</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">indata</span><span class="p">[:,</span> <span class="mi">0</span><span class="p">].</span><span class="nf">astype</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">float32</span><span class="p">)</span>
    <span class="n">pitched</span> <span class="o">=</span> <span class="nf">pitch_shift_simple</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">pitch_ratio</span><span class="p">)</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">zeros_like</span><span class="p">(</span><span class="n">pitched</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">sample</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">pitched</span><span class="p">):</span>
        <span class="n">delayed</span> <span class="o">=</span> <span class="n">delay_buffer</span><span class="p">[</span><span class="n">write_pos</span><span class="p">]</span>
        <span class="n">y</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">sample</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">mix</span><span class="p">)</span> <span class="o">+</span> <span class="n">delayed</span> <span class="o">*</span> <span class="n">mix</span>
        <span class="n">delay_buffer</span><span class="p">[</span><span class="n">write_pos</span><span class="p">]</span> <span class="o">=</span> <span class="n">sample</span> <span class="o">+</span> <span class="n">delayed</span> <span class="o">*</span> <span class="n">feedback</span>
        <span class="n">write_pos</span> <span class="o">=</span> <span class="p">(</span><span class="n">write_pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">delay_samples</span>

    <span class="n">outdata</span><span class="p">[:,</span> <span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">y</span>

<span class="k">with</span> <span class="n">sd</span><span class="p">.</span><span class="nc">Stream</span><span class="p">(</span><span class="n">channels</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">samplerate</span><span class="o">=</span><span class="n">fs</span><span class="p">,</span> <span class="n">blocksize</span><span class="o">=</span><span class="n">block</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="n">callback</span><span class="p">):</span>
    <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">Efekt pedalı çalışıyor. Durdurmak için Ctrl+C.</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
        <span class="n">sd</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">delay_buffer</code> geçmiş sesi saklayan dairesel hafızadır. <code class="language-plaintext highlighter-rouge">write_pos</code> sona gelince başa döner; böylece sonsuz uzunlukta dizi kullanmadan yankı üretiriz. Pitch kısmı bilerek sade tutuldu: amaç algoritmanın iskeletini görmek. Daha pürüzsüz sonuç için pencereleme, overlap-add ve faz sürekliliği gerekir.</p>

<p>ALSA loopback yönlendirmesi için <code class="language-plaintext highlighter-rouge">pavucontrol</code>, PipeWire patchbay araçları veya doğrudan <code class="language-plaintext highlighter-rouge">.asoundrc</code> kullanılabilir. Basit testlerde mikrofonu Python uygulamasına giriş, uygulama çıkışını da Loopback oynatma cihazına vermek yeterlidir. Ardından OBS, DAW veya başka bir kayıt aracı Loopback yakalama tarafını dinleyebilir.</p>

<table>
  <thead>
    <tr>
      <th>Parametre</th>
      <th>Küçük Değer</th>
      <th>Büyük Değer</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Buffer</td>
      <td>Az gecikme, riskli CPU</td>
      <td>Stabil, hissedilir gecikme</td>
    </tr>
    <tr>
      <td>Feedback</td>
      <td>Kısa yankı</td>
      <td>Uzayan tekrarlar</td>
    </tr>
    <tr>
      <td>Mix</td>
      <td>Doğal sinyal baskın</td>
      <td>Efekt baskın</td>
    </tr>
    <tr>
      <td>Pitch ratio</td>
      <td>Pesleşme</td>
      <td>Tizleşme</td>
    </tr>
  </tbody>
</table>

<p>Sonuçta ALSA loopback bize sanal kabloyu, Python/DSP kodu ise pedalın elektronik devresini verir. Birkaç parametreyi MIDI kontrolcüye bağlayarak gerçek bir sahne pedalına yaklaşabilir; hatta zincire distortion, chorus ve compressor ekleyerek Linux tabanlı kendi mini efekt istasyonunuzu kurabilirsiniz.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="ALSA" /><category term="Linux Audio" /><category term="DSP" /><category term="Python" /><category term="Ses Efekti" /><summary type="html"><![CDATA[Linux üzerinde gitar pedalı gibi çalışan bir ses efekti sistemi kurmak kulağa stüdyo büyüsü gibi gelebilir; ama ALSA’nın loopback cihazı ve biraz DSP bilgisiyle mikrofon girişini yakalayıp yankı ve pitch değişimi uygulayan gerçek zamanlı bir pedal yapmak gayet mümkün. Bu yazıda hedefimiz: mikrofonu sanal bir ses hattına bağlamak, sesi küçük tamponlar halinde işlemek ve çıktıyı hoparlöre ya da başka bir uygulamaya göndermek.]]></summary></entry><entry><title type="html">Değişkenler, Veri Tipleri ve Güvenli Dönüşümler: Statik Tiplerin Gizli Düzeni</title><link href="https://sonsuzus.github.io/posts/degiskenler-veri-tipleri-ve-guvenli-donusumler-statik-tiplerin-gizli-duzeni/" rel="alternate" type="text/html" title="Değişkenler, Veri Tipleri ve Güvenli Dönüşümler: Statik Tiplerin Gizli Düzeni" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/degiskenler-veri-tipleri-ve-guvenli-donusumler-statik-tiplerin-gizli-duzeni</id><content type="html" xml:base="https://sonsuzus.github.io/posts/degiskenler-veri-tipleri-ve-guvenli-donusumler-statik-tiplerin-gizli-duzeni/"><![CDATA[<p>Programlamada değişkenler, veriyi sakladığımız küçük kutular gibi anlatılır; ama işin arka tarafında derleyicinin yürüttüğü ciddi bir kimlik kontrolü vardır. Bir değerin sayı mı, metin mi, mantıksal sonuç mu olduğunu bilmek; hataları erken yakalamak, belleği doğru kullanmak ve kodun niyetini açık göstermek için kritiktir.</p>

<p>``</p>

<p>Statik tip sisteminde bir değişkenin tipi çalışma zamanında rastgele değişmez; çoğu karar derleme aşamasında verilir. Yani program henüz çalışmadan önce derleyici şunu sorar: “Bu değişkene gerçekten bu değer atanabilir mi?” Eğer cevap hayırsa, program daha başlangıç çizgisine gelmeden uyarı alırız. Bu, özellikle büyük projelerde süper güç gibidir; çünkü hatayı kullanıcı değil, derleyici yakalar.</p>

<p>Basit düşünelim: <code class="language-plaintext highlighter-rouge">int</code> tam sayıları, <code class="language-plaintext highlighter-rouge">double</code> ondalıklı sayıları, <code class="language-plaintext highlighter-rouge">string</code> metinleri, <code class="language-plaintext highlighter-rouge">bool</code> ise doğru/yanlış değerlerini taşır. Matematiksel olarak bir tipin alabileceği değerleri bir küme gibi düşünebiliriz. Örneğin 32 bitlik işaretli bir tam sayı yaklaşık olarak şu aralıktadır: $-2^{31}$ ile $2^{31}-1$ arası. Bu aralığın dışındaki bir değeri <code class="language-plaintext highlighter-rouge">int</code> içine koymaya çalışmak, küçük bir bavula piyano sığdırmaya benzer.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Açıklama</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Değişken</td>
      <td>Bellekte isimlendirilmiş veri alanı</td>
      <td><code class="language-plaintext highlighter-rouge">age</code></td>
    </tr>
    <tr>
      <td>Veri tipi</td>
      <td>Değerin biçimini ve sınırlarını belirler</td>
      <td><code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">string</code></td>
    </tr>
    <tr>
      <td>Statik tip</td>
      <td>Tip derleme zamanında bilinir</td>
      <td><code class="language-plaintext highlighter-rouge">int count = 5;</code></td>
    </tr>
    <tr>
      <td>Dinamik tip</td>
      <td>Tip çalışma zamanında değişebilir</td>
      <td>Bazı script dilleri</td>
    </tr>
  </tbody>
</table>

<p>Statik tipli dillerde tipleri her zaman uzun uzun yazmak zorunda değiliz. Burada otomatik tip belirleme, yani type inference devreye girer. Derleyici sağ taraftaki değere bakarak sol taraftaki değişkenin tipini çıkarır. Ancak bu, değişkenin tipsiz olduğu anlamına gelmez; sadece tipi bizim yerimize derleyici yazar.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">count</span> <span class="p">=</span> <span class="m">10</span><span class="p">;</span>        <span class="c1">// Derleyici bunu int olarak belirler</span>
<span class="kt">var</span> <span class="n">price</span> <span class="p">=</span> <span class="m">19.99</span><span class="p">;</span>     <span class="c1">// double</span>
<span class="kt">var</span> <span class="n">name</span> <span class="p">=</span> <span class="s">"Ada"</span><span class="p">;</span>      <span class="c1">// string</span>
<span class="kt">var</span> <span class="n">isActive</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span>   <span class="c1">// bool</span>

<span class="c1">// count = "on";       // Hata: count artık int kabul edilir</span>
</code></pre></div></div>

<p>Bu örnekte <code class="language-plaintext highlighter-rouge">var</code>, “ne olursa olsun kabul et” demek değildir. Daha çok “tipi sağ taraftan anla ama sonra sıkı denetle” demektir. Yani type inference, statik tip sistemini zayıflatmaz; sadece daha az klavye mesaisi sağlar.</p>

<p>Tip dönüşümleri ise iki ana gruba ayrılır: örtük ve açık dönüşüm. Örtük dönüşüm güvenli kabul edilen, veri kaybı beklenmeyen durumlarda yapılır. Açık dönüşümde ise programcı sorumluluğu üstlenir: “Evet, bunun riskli olabileceğini biliyorum.”</p>

<table>
  <thead>
    <tr>
      <th>Dönüşüm Türü</th>
      <th style="text-align: right">Güvenlik</th>
      <th>Örnek</th>
      <th>Risk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Örtük dönüşüm</td>
      <td style="text-align: right">Yüksek</td>
      <td><code class="language-plaintext highlighter-rouge">int</code> → <code class="language-plaintext highlighter-rouge">long</code></td>
      <td>Genelde yok</td>
    </tr>
    <tr>
      <td>Açık dönüşüm</td>
      <td style="text-align: right">Orta</td>
      <td><code class="language-plaintext highlighter-rouge">double</code> → <code class="language-plaintext highlighter-rouge">int</code></td>
      <td>Ondalık kısım kaybolur</td>
    </tr>
    <tr>
      <td>Parse işlemi</td>
      <td style="text-align: right">Girdiye bağlı</td>
      <td><code class="language-plaintext highlighter-rouge">string</code> → <code class="language-plaintext highlighter-rouge">int</code></td>
      <td>Geçersiz metin</td>
    </tr>
    <tr>
      <td>TryParse</td>
      <td style="text-align: right">Daha güvenli</td>
      <td>Kontrollü parse</td>
      <td>Hata yönetilebilir</td>
    </tr>
  </tbody>
</table>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">small</span> <span class="p">=</span> <span class="m">42</span><span class="p">;</span>
<span class="kt">long</span> <span class="n">big</span> <span class="p">=</span> <span class="n">small</span><span class="p">;</span> <span class="c1">// Örtük dönüşüm: int değeri long içine rahatça sığar</span>

<span class="kt">double</span> <span class="n">ratio</span> <span class="p">=</span> <span class="m">9.75</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">roundedDown</span> <span class="p">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">ratio</span><span class="p">;</span> <span class="c1">// Açık dönüşüm: sonuç 9 olur</span>
</code></pre></div></div>

<p>Buradaki dönüşümde $9.75 \rightarrow 9$ olur; yani bilgi kaybı yaşanır. Bu yüzden açık dönüşümler kodda küçük bir sarı ikaz levhası gibi okunmalıdır. “Burada bilinçli bir karar var” mesajı verir.</p>

<p>Kullanıcıdan veya dosyadan gelen veriler genellikle metindir. Bu metni sayıya çevirmek için doğrudan parse etmek yerine güvenli yöntemler tercih edilmelidir.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">string</span> <span class="n">input</span> <span class="p">=</span> <span class="s">"123"</span><span class="p">;</span>

<span class="k">if</span> <span class="p">(</span><span class="kt">int</span><span class="p">.</span><span class="nf">TryParse</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="k">out</span> <span class="kt">int</span> <span class="n">number</span><span class="p">))</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">result</span> <span class="p">=</span> <span class="n">number</span> <span class="p">*</span> <span class="m">2</span><span class="p">;</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
    <span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Geçerli bir sayı girilmedi."</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">TryParse</code>, programı patlatmadan sonucu kontrol etmemizi sağlar. Kullanıcı <code class="language-plaintext highlighter-rouge">abc</code> yazarsa uygulama dramatik bir tiyatro sahnesi gibi çökmez; sadece uygun mesajı verir.</p>

<p>Bazı diller taşma kontrolleri için özel mekanizmalar sunar. Örneğin çok büyük bir sayıyı küçük tipe çevirirken değer aralığı aşılabilir. Bu durumda $x \notin [min, max]$ ise dönüşüm güvenli değildir.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">checked</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">max</span> <span class="p">=</span> <span class="kt">int</span><span class="p">.</span><span class="n">MaxValue</span><span class="p">;</span>
    <span class="c1">// int overflow = max + 1; // Taşma hatası üretir</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Özetle değişkenler veriyi taşır, veri tipleri bu verinin kurallarını belirler, statik tip sistemi de oyunun hakemi gibi yanlış pasları erkenden düdükler. Type inference kodu sadeleştirirken güvenliği korur. Tip dönüşümlerinde ise temel soru hep aynıdır: “Bu değer hedef tipe kayıpsız ve anlamlı biçimde sığar mı?” Bu soruyu alışkanlık haline getirmek, daha sağlam ve okunabilir programlar yazmanın en pratik yollarından biridir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="değişkenler" /><category term="veri tipleri" /><category term="type inference" /><category term="statik tip" /><category term="tip dönüşümü" /><summary type="html"><![CDATA[Programlamada değişkenler, veriyi sakladığımız küçük kutular gibi anlatılır; ama işin arka tarafında derleyicinin yürüttüğü ciddi bir kimlik kontrolü vardır. Bir değerin sayı mı, metin mi, mantıksal sonuç mu olduğunu bilmek; hataları erken yakalamak, belleği doğru kullanmak ve kodun niyetini açık göstermek için kritiktir.]]></summary></entry></feed>