<?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-23T07:13:57+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">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><entry><title type="html">Fonksiyonlar ve Çoklu Geri Dönüş Değerleri: Modüler Kodun Süper Gücü</title><link href="https://sonsuzus.github.io/posts/fonksiyonlar-ve-coklu-geri-donus-degerleri-moduler-kodun-super-gucu/" rel="alternate" type="text/html" title="Fonksiyonlar ve Çoklu Geri Dönüş Değerleri: Modüler Kodun Süper Gücü" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/fonksiyonlar-ve-coklu-geri-donus-degerleri-moduler-kodun-super-gucu</id><content type="html" xml:base="https://sonsuzus.github.io/posts/fonksiyonlar-ve-coklu-geri-donus-degerleri-moduler-kodun-super-gucu/"><![CDATA[<p>Kod yazarken aynı işlemi tekrar tekrar kopyalamak, mutfakta her çay demleyişte ocağı yeniden icat etmeye benzer. Fonksiyonlar tam da bu noktada devreye girer: Bir işi isimlendirir, sınırlarını çizer ve gerektiğinde çağırmamızı sağlar. Daha da güzeli, bazı dillerde bir fonksiyon tek seferde birden fazla sonuç döndürebilir; örneğin hem işlem sonucunu hem de durum bilgisini aynı anda almak mümkündür.
``</p>

<h2 id="fonksiyon-nedir-neden-bu-kadar-önemlidir">Fonksiyon Nedir, Neden Bu Kadar Önemlidir?</h2>

<p>Teorik olarak bir fonksiyon, belirli girdileri alıp belirli çıktılar üreten bir dönüşüm olarak düşünülebilir. Matematiksel gösterimle:</p>

<p>$f: X \rightarrow Y$</p>

<p>Burada $X$ giriş kümesini, $Y$ ise çıkış kümesini temsil eder. Programlamada ise bu fikir biraz daha genişler: Fonksiyonlar yalnızca değer döndürmez, bazen dosya yazabilir, ekrana çıktı verebilir veya veritabanına kayıt atabilir. Yani yan etki, yani <em>side effect</em>, programlama dünyasında önemli bir kavramdır.</p>

<p>Bir fonksiyonun temel parçaları şunlardır:</p>

<table>
  <thead>
    <tr>
      <th>Parça</th>
      <th>Açıklama</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>İsim</td>
      <td>Fonksiyonu çağırmak için kullanılır</td>
      <td><code class="language-plaintext highlighter-rouge">topla</code></td>
    </tr>
    <tr>
      <td>Parametre</td>
      <td>Fonksiyona verilen girişlerdir</td>
      <td><code class="language-plaintext highlighter-rouge">a</code>, <code class="language-plaintext highlighter-rouge">b</code></td>
    </tr>
    <tr>
      <td>Gövde</td>
      <td>İşlemin yapıldığı bölümdür</td>
      <td><code class="language-plaintext highlighter-rouge">a + b</code></td>
    </tr>
    <tr>
      <td>Geri dönüş</td>
      <td>Sonucun dışarı verildiği kısımdır</td>
      <td><code class="language-plaintext highlighter-rouge">return sonuc</code></td>
    </tr>
  </tbody>
</table>

<p>İyi tasarlanmış bir fonksiyon küçük, anlaşılır ve tek sorumluluğa sahip olmalıdır. Bu prensip, büyük projelerde kodun okunabilirliğini ciddi biçimde artırır.</p>

<h2 id="çoklu-geri-dönüş-değeri-ne-demek">Çoklu Geri Dönüş Değeri Ne Demek?</h2>

<p>Normalde bir fonksiyonun tek bir sonuç döndürdüğünü düşünürüz. Fakat pratikte çoğu zaman birden fazla bilgiye ihtiyaç duyarız. Örneğin bir bölme işlemi yaparken hem bölümü hem kalanı almak isteyebiliriz. Matematikte bu, çıktının tek bir değer değil, bir çift olması anlamına gelir:</p>

<p>$f: A \rightarrow B \times C$</p>

<p>Buradaki $B \times C$, iki değerden oluşan bir ürün tipidir. Python gibi dillerde bu çoğunlukla tuple ile temsil edilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">bol_ve_kalan</span><span class="p">(</span><span class="n">sayi</span><span class="p">,</span> <span class="n">bolen</span><span class="p">):</span>
    <span class="n">bolum</span> <span class="o">=</span> <span class="n">sayi</span> <span class="o">//</span> <span class="n">bolen</span>
    <span class="n">kalan</span> <span class="o">=</span> <span class="n">sayi</span> <span class="o">%</span> <span class="n">bolen</span>
    <span class="k">return</span> <span class="n">bolum</span><span class="p">,</span> <span class="n">kalan</span>

<span class="n">b</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="nf">bol_ve_kalan</span><span class="p">(</span><span class="mi">17</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Bölüm:</span><span class="sh">'</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Kalan:</span><span class="sh">'</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span>
</code></pre></div></div>

<p>Bu kodda fonksiyon iki değer döndürür: <code class="language-plaintext highlighter-rouge">bolum</code> ve <code class="language-plaintext highlighter-rouge">kalan</code>. Python aslında bunları perde arkasında bir tuple olarak paketler. Yani <code class="language-plaintext highlighter-rouge">return bolum, kalan</code> ifadesi kabaca <code class="language-plaintext highlighter-rouge">return (bolum, kalan)</code> gibidir.</p>

<h2 id="tek-değer-mi-çoklu-değer-mi">Tek Değer mi, Çoklu Değer mi?</h2>

<p>Çoklu dönüş her zaman daha iyi değildir. Bazen kodu sadeleştirir, bazen de anlamı bulanıklaştırır. Karar verirken aşağıdaki karşılaştırma işe yarar:</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
      <th>Ne Zaman Kullanılır?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tek değer döndürme</td>
      <td>Basit ve okunabilir</td>
      <td>Ek bilgi taşımakta zorlanır</td>
      <td>Basit hesaplamalar</td>
    </tr>
    <tr>
      <td>Çoklu değer döndürme</td>
      <td>Birden fazla sonucu pratik verir</td>
      <td>Sıra karışırsa hata doğar</td>
      <td>Bölüm-kalan, sonuç-hata gibi durumlar</td>
    </tr>
    <tr>
      <td>Nesne/dict döndürme</td>
      <td>Anlamlı alan adları sağlar</td>
      <td>Biraz daha uzun yazılır</td>
      <td>Karmaşık sonuçlar</td>
    </tr>
  </tbody>
</table>

<p>Örneğin kullanıcı doğrulama fonksiyonunda hem başarı durumunu hem de mesajı döndürmek oldukça kullanışlıdır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">kullanici_kontrol</span><span class="p">(</span><span class="n">ad</span><span class="p">,</span> <span class="n">sifre</span><span class="p">):</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">ad</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span><span class="p">,</span> <span class="sh">'</span><span class="s">Kullanıcı adı boş olamaz</span><span class="sh">'</span>
    <span class="k">if</span> <span class="nf">len</span><span class="p">(</span><span class="n">sifre</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">8</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span><span class="p">,</span> <span class="sh">'</span><span class="s">Şifre en az 8 karakter olmalı</span><span class="sh">'</span>
    <span class="k">return</span> <span class="bp">True</span><span class="p">,</span> <span class="sh">'</span><span class="s">Giriş bilgileri geçerli</span><span class="sh">'</span>

<span class="n">basarili</span><span class="p">,</span> <span class="n">mesaj</span> <span class="o">=</span> <span class="nf">kullanici_kontrol</span><span class="p">(</span><span class="sh">'</span><span class="s">ada</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">1234567</span><span class="sh">'</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">mesaj</span><span class="p">)</span>
</code></pre></div></div>

<p>Burada ilk değer mantıksal sonucu, ikinci değer ise açıklamayı temsil eder. Bu desen özellikle hata yönetiminde çok sevilir.</p>

<h2 id="daha-okunabilir-alternatif-sözlük-döndürmek">Daha Okunabilir Alternatif: Sözlük Döndürmek</h2>

<p>Eğer dönen değer sayısı artıyorsa tuple yerine sözlük döndürmek daha açıklayıcı olabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">analiz_et</span><span class="p">(</span><span class="n">metin</span><span class="p">):</span>
    <span class="n">kelimeler</span> <span class="o">=</span> <span class="n">metin</span><span class="p">.</span><span class="nf">split</span><span class="p">()</span>
    <span class="k">return</span> <span class="p">{</span>
        <span class="sh">'</span><span class="s">karakter_sayisi</span><span class="sh">'</span><span class="p">:</span> <span class="nf">len</span><span class="p">(</span><span class="n">metin</span><span class="p">),</span>
        <span class="sh">'</span><span class="s">kelime_sayisi</span><span class="sh">'</span><span class="p">:</span> <span class="nf">len</span><span class="p">(</span><span class="n">kelimeler</span><span class="p">),</span>
        <span class="sh">'</span><span class="s">ilk_kelime</span><span class="sh">'</span><span class="p">:</span> <span class="n">kelimeler</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">kelimeler</span> <span class="k">else</span> <span class="bp">None</span>
    <span class="p">}</span>

<span class="n">sonuc</span> <span class="o">=</span> <span class="nf">analiz_et</span><span class="p">(</span><span class="sh">'</span><span class="s">Fonksiyonlar kodu düzenler</span><span class="sh">'</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">sonuc</span><span class="p">[</span><span class="sh">'</span><span class="s">kelime_sayisi</span><span class="sh">'</span><span class="p">])</span>
</code></pre></div></div>

<p>Bu yöntem, özellikle ekip çalışmalarında yanlış sırayla değişken atama riskini azaltır. <code class="language-plaintext highlighter-rouge">a, b, c</code> gibi belirsiz isimler yerine <code class="language-plaintext highlighter-rouge">kelime_sayisi</code> gibi açık alanlar kullanılır.</p>

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

<p>Fonksiyonlar, modüler kod yazmanın temel taşıdır. Kod tekrarını azaltır, test etmeyi kolaylaştırır ve karmaşık problemleri küçük parçalara böler. Çoklu geri dönüş değerleri ise fonksiyonları daha ifade gücü yüksek hale getirir. Ancak önemli kural şudur: Dönen değerler gerçekten birlikte anlamlıysa çoklu dönüş kullan; sayı arttığında ise sözlük, sınıf veya özel veri yapılarıyla kodu daha okunabilir hale getir. Kısacası fonksiyonlar kodun lego parçalarıysa, çoklu dönüş değerleri de aynı kutudan çıkan bonus parçalar gibidir: Doğru yerde kullanıldığında yapıyı hem sağlamlaştırır hem de eğlenceli hale getirir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="fonksiyonlar" /><category term="modüler kod" /><category term="çoklu geri dönüş" /><summary type="html"><![CDATA[Kod yazarken aynı işlemi tekrar tekrar kopyalamak, mutfakta her çay demleyişte ocağı yeniden icat etmeye benzer. Fonksiyonlar tam da bu noktada devreye girer: Bir işi isimlendirir, sınırlarını çizer ve gerektiğinde çağırmamızı sağlar. Daha da güzeli, bazı dillerde bir fonksiyon tek seferde birden fazla sonuç döndürebilir; örneğin hem işlem sonucunu hem de durum bilgisini aynı anda almak mümkündür.]]></summary></entry><entry><title type="html">Go Kurulumu ve VS Code ile Sade Geliştirme Ortamı Hazırlama</title><link href="https://sonsuzus.github.io/posts/go-kurulumu-ve-vs-code-ile-sade-gelistirme-ortami-hazirlama/" rel="alternate" type="text/html" title="Go Kurulumu ve VS Code ile Sade Geliştirme Ortamı Hazırlama" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/go-kurulumu-ve-vs-code-ile-sade-gelistirme-ortami-hazirlama</id><content type="html" xml:base="https://sonsuzus.github.io/posts/go-kurulumu-ve-vs-code-ile-sade-gelistirme-ortami-hazirlama/"><![CDATA[<p>Go öğrenmeye başlamak, yeni bir müzik aleti almak gibidir: önce akort edersin, sonra şarkı çalmaya başlarsın. Bu yazıda Go derleyicisini kurup VS Code üzerinde sade, hızlı ve teoriyi pratiğe çevirmeye uygun bir geliştirme ortamı hazırlayacağız. Amacımız “her şeyi kurdum ama neden çalışmıyor?” paniğini azaltmak ve ilk Go programını güvenle koşturmak.
``
Go, Google tarafından geliştirilen derlenebilir, statik tipli ve sade söz dizimine sahip bir programlama dilidir. Derlenebilir olması şu anlama gelir: yazdığınız <code class="language-plaintext highlighter-rouge">.go</code> dosyaları doğrudan makineye daha yakın çalıştırılabilir programa dönüştürülür. Kabaca süreç şöyle düşünülebilir: kaynak kod $K$, derleyici $D$ tarafından işlenir ve çalıştırılabilir çıktı $C$ üretilir: $D(K) = C$. Bu model, Go’nun hızlı çalışmasına ve dağıtımının kolay olmasına katkı sağlar.</p>

<p>Kuruluma başlamadan önce birkaç temel kavramı netleştirelim:</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Ne işe yarar?</th>
      <th>Kısaca benzetme</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Go derleyicisi</td>
      <td>Kodunuzu çalıştırılabilir hale getirir</td>
      <td>Tercüman</td>
    </tr>
    <tr>
      <td>GOROOT</td>
      <td>Go’nun kurulu olduğu ana dizindir</td>
      <td>Fabrikanın kendisi</td>
    </tr>
    <tr>
      <td>GOPATH</td>
      <td>Eski çalışma alanı yaklaşımıdır</td>
      <td>Eski usul depo</td>
    </tr>
    <tr>
      <td>Go Modules</td>
      <td>Modern bağımlılık yönetimidir</td>
      <td>Proje bazlı paket çantası</td>
    </tr>
    <tr>
      <td>gopls</td>
      <td>VS Code’a Go zekâsı kazandırır</td>
      <td>Kod editörünün gözlüğü</td>
    </tr>
  </tbody>
</table>

<p>İlk adım Go’yu kurmak. Resmî site olan <code class="language-plaintext highlighter-rouge">https://go.dev/dl/</code> adresine gidin ve işletim sisteminize uygun paketi indirin. Windows kullanıyorsanız <code class="language-plaintext highlighter-rouge">.msi</code> kurulum dosyası genellikle yeterlidir. macOS tarafında <code class="language-plaintext highlighter-rouge">.pkg</code> dosyası veya Homebrew ile <code class="language-plaintext highlighter-rouge">brew install go</code> kullanılabilir. Linux’ta paket yöneticinizden kurabilir ya da resmî arşivi <code class="language-plaintext highlighter-rouge">/usr/local</code> altına açabilirsiniz.</p>

<p>Kurulumdan sonra terminali açıp şu komutu çalıştırın:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go version
</code></pre></div></div>

<p>Bu komut size kurulu Go sürümünü göstermelidir. Örneğin <code class="language-plaintext highlighter-rouge">go version go1.22 linux/amd64</code> gibi bir çıktı görüyorsanız tebrikler, derleyici sahneye çıktı! Eğer komut bulunamıyorsa sorun büyük ihtimalle PATH ayarındadır. PATH, işletim sisteminin komutları nerede arayacağını belirleyen listedir. Matematiksel düşünürsek çalıştırılabilir dosya arama işlemi bir küme üzerinde yapılır: $PATH = {d_1, d_2, d_3, …}$. Go’nun <code class="language-plaintext highlighter-rouge">bin</code> klasörü bu kümeye eklenmelidir.</p>

<p>Şimdi VS Code tarafına geçelim. VS Code’u açın, Extensions bölümüne girin ve Microsoft tarafından sağlanan <code class="language-plaintext highlighter-rouge">Go</code> eklentisini kurun. Bu eklenti tek başına güzeldir ama asıl sihir <code class="language-plaintext highlighter-rouge">gopls</code> ile gelir. Bir <code class="language-plaintext highlighter-rouge">.go</code> dosyası açtığınızda VS Code genellikle eksik araçları kurmak isteyecektir. Onay verin; otomatik tamamlama, hata işaretleme, biçimlendirme ve tanıma özellikleri aktif olacaktır.</p>

<p>Aşağıdaki tablo, sade bir Go geliştirme ortamında hangi parçanın ne kattığını özetler:</p>

<table>
  <thead>
    <tr>
      <th>Araç</th>
      <th style="text-align: right">Zorunlu mu?</th>
      <th>Sağladığı fayda</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Go SDK</td>
      <td style="text-align: right">Evet</td>
      <td>Derleme, çalıştırma, test</td>
    </tr>
    <tr>
      <td>VS Code</td>
      <td style="text-align: right">Hayır ama önerilir</td>
      <td>Hafif editör deneyimi</td>
    </tr>
    <tr>
      <td>Go eklentisi</td>
      <td style="text-align: right">Evet, VS Code için</td>
      <td>Dil desteği</td>
    </tr>
    <tr>
      <td>gopls</td>
      <td style="text-align: right">Çok önerilir</td>
      <td>Akıllı tamamlama, analiz</td>
    </tr>
    <tr>
      <td>Git</td>
      <td style="text-align: right">Önerilir</td>
      <td>Sürüm kontrolü ve modül kullanımı</td>
    </tr>
  </tbody>
</table>

<p>Artık küçük bir proje oluşturalım. Terminalde şu adımları uygulayın:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>merhaba-go
<span class="nb">cd </span>merhaba-go
go mod init example.com/merhaba-go
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">go mod init</code>, projeniz için bir <code class="language-plaintext highlighter-rouge">go.mod</code> dosyası üretir. Bu dosya, projenin kimliği ve bağımlılıkları için merkezdir. Modern Go geliştirmede proje formülü kabaca şöyledir: proje = kaynak kod + <code class="language-plaintext highlighter-rouge">go.mod</code> + bağımlılıklar.</p>

<p>Şimdi <code class="language-plaintext highlighter-rouge">main.go</code> dosyasını oluşturun:</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">mesaj</span> <span class="o">:=</span> <span class="s">"Merhaba Go, ben geldim!"</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">mesaj</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">package main</code>, çalıştırılabilir bir program yazdığımızı söyler. <code class="language-plaintext highlighter-rouge">import "fmt"</code>, ekrana yazı basmak için standart kütüphaneden <code class="language-plaintext highlighter-rouge">fmt</code> paketini getirir. <code class="language-plaintext highlighter-rouge">main</code> fonksiyonu ise programın başlangıç noktasıdır. <code class="language-plaintext highlighter-rouge">mesaj :=</code> ifadesi Go’nun kısa değişken tanımlama biçimidir; derleyici türü kendisi çıkarır.</p>

<p>Programı çalıştırmak için:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go run <span class="nb">.</span>
</code></pre></div></div>

<p>Derlemek isterseniz:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go build
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">go run</code> hızlı denemeler için idealdir; <code class="language-plaintext highlighter-rouge">go build</code> ise çalıştırılabilir çıktı üretir. Yani <code class="language-plaintext highlighter-rouge">go run</code> mutfakta tadım yapmak, <code class="language-plaintext highlighter-rouge">go build</code> ise yemeği tabağa koymaktır.</p>

<p>Son olarak VS Code ayarlarında <code class="language-plaintext highlighter-rouge">Format On Save</code> seçeneğini açmanızı öneririm. Go kültüründe biçimlendirme tartışması minimumdur; <code class="language-plaintext highlighter-rouge">gofmt</code> ne derse o olur. Bu da ekip içinde “süslü parantez sağda mı solda mı?” savaşlarını bitirir.</p>

<p>Özetle: Go SDK’yı kurduk, PATH kontrolünü yaptık, VS Code’a Go eklentisini ve <code class="language-plaintext highlighter-rouge">gopls</code> desteğini ekledik, modül tabanlı bir proje başlattık ve ilk programı çalıştırdık. Artık teoriyi pratiğe dökecek temiz bir masanız var. Bundan sonrası değişkenler, fonksiyonlar, paketler ve bol bol “aa bu dil baya sadeymiş” anı!</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="go" /><category term="golang" /><category term="vscode" /><category term="kurulum" /><category term="geliştirme ortamı" /><summary type="html"><![CDATA[Go öğrenmeye başlamak, yeni bir müzik aleti almak gibidir: önce akort edersin, sonra şarkı çalmaya başlarsın. Bu yazıda Go derleyicisini kurup VS Code üzerinde sade, hızlı ve teoriyi pratiğe çevirmeye uygun bir geliştirme ortamı hazırlayacağız. Amacımız “her şeyi kurdum ama neden çalışmıyor?” paniğini azaltmak ve ilk Go programını güvenle koşturmak.]]></summary></entry><entry><title type="html">Go Temelleri ve C/C++ ile Karşılaştırma: Sadelik, Güvenlik ve Felsefe</title><link href="https://sonsuzus.github.io/posts/go-temelleri-ve-cc-ile-karsilastirma-sadelik-guvenlik-ve-felsefe/" rel="alternate" type="text/html" title="Go Temelleri ve C/C++ ile Karşılaştırma: Sadelik, Güvenlik ve Felsefe" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/go-temelleri-ve-cc-ile-karsilastirma-sadelik-guvenlik-ve-felsefe</id><content type="html" xml:base="https://sonsuzus.github.io/posts/go-temelleri-ve-cc-ile-karsilastirma-sadelik-guvenlik-ve-felsefe/"><![CDATA[<p>Go, yani Gopher’ların neşeli dünyası, ilk bakışta C ailesinden gelmiş gibi görünür: süslü parantezler, tipler, fonksiyonlar… Fakat birkaç satır yazınca anlarız ki Go’nun derdi yalnızca kod çalıştırmak değil, geliştiriciyi karmaşadan korumaktır. C/C++ bize büyük güç ve büyük sorumluluk verirken, Go daha çok “ekipçe okunabilir, hızlı derlenebilir, güvenli varsayılanlara sahip yazılım” fikrini merkeze alır.
``</p>

<p>Go’nun sözdizimi C’ye benzer ama felsefesi farklıdır. C ve C++ tarihsel olarak donanıma yakınlık, performans ve düşük seviyeli kontrol üzerine kuruludur. Go ise modern sunucu yazılımları, ağ programlama, eşzamanlılık ve bakım kolaylığı için tasarlanmıştır. Bu farkı kabaca şöyle düşünebiliriz: C/C++ programcıya motorun tüm parçalarını verir; Go ise iyi ayarlanmış bir araç sunar ve gereksiz kolları panelden kaldırır.</p>

<p>Teorik olarak bir dilin karmaşıklığını $K$ ile, üretkenliği $U$ ile gösterirsek basit bir sezgisel ilişki kurabiliriz: $U \approx \frac{Okunabilirlik + Araçlama}{Karmaşıklık}$. Go, bu denklemde karmaşıklık paydasını küçültmeye çalışır. Örneğin header dosyaları yoktur, sınıf hiyerarşisi yoktur, kalıtım yerine arayüzler ve bileşim tercih edilir.</p>

<table>
  <thead>
    <tr>
      <th>Konu</th>
      <th>C</th>
      <th>C++</th>
      <th>Go</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Derleme modeli</td>
      <td>Header + kaynak dosya</td>
      <td>Header, template, linker karmaşası</td>
      <td>Paket tabanlı, hızlı derleme</td>
    </tr>
    <tr>
      <td>Nesne yaklaşımı</td>
      <td>Yok</td>
      <td>Sınıf ve kalıtım</td>
      <td>Struct + interface</td>
    </tr>
    <tr>
      <td>Bellek yönetimi</td>
      <td>Manuel</td>
      <td>Manuel/RAII/akıllı pointer</td>
      <td>Çöp toplayıcı</td>
    </tr>
    <tr>
      <td>Eşzamanlılık</td>
      <td>Kütüphane bağımlı</td>
      <td>Thread, async, future</td>
      <td>Goroutine ve channel</td>
    </tr>
    <tr>
      <td>Felsefe</td>
      <td>Donanıma yakınlık</td>
      <td>Esneklik ve performans</td>
      <td>Sadelik ve okunabilirlik</td>
    </tr>
  </tbody>
</table>

<p>Go’da değişken tanımlama oldukça yalındır. C/C++’ta tip genelde soldadır; Go’da ise isim önce gelir. Bu küçük fark, özellikle karmaşık tiplerde okunabilirliği artırı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="s">"fmt"</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">name</span> <span class="o">:=</span> <span class="s">"Ada"</span>
    <span class="n">age</span> <span class="o">:=</span> <span class="m">32</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">age</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">:=</code> kısa değişken tanımlama operatörüdür. Derleyici tipleri çıkarır; <code class="language-plaintext highlighter-rouge">name</code> string, <code class="language-plaintext highlighter-rouge">age</code> int olur. C++ tarafında <code class="language-plaintext highlighter-rouge">auto</code> benzer bir kolaylık sunar ama Go bu yaklaşımı dilin doğal parçası haline getirir. Yine de Go tamamen dinamik değildir; tipler derleme zamanında bellidir. Yani $tip\ güvenliği + kısa\ yazım$ hedeflenir.</p>

<p>Fonksiyonlarda dönüş değerleri de Go’nun karakteristik alanlarından biridir. Birden fazla değer döndürmek olağandır; hata yönetimi çoğunlukla <code class="language-plaintext highlighter-rouge">error</code> değeriyle yapılır.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">divide</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="kt">float64</span><span class="p">)</span> <span class="p">(</span><span class="kt">float64</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="n">b</span> <span class="o">==</span> <span class="m">0</span> <span class="p">{</span>
        <span class="k">return</span> <span class="m">0</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">"sıfıra bölme"</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">a</span> <span class="o">/</span> <span class="n">b</span><span class="p">,</span> <span class="no">nil</span>
<span class="p">}</span>
</code></pre></div></div>

<p>C’de hata kodları, C++’ta exception mekanizması sık görülür. Go ise hatayı görünür kılar: fonksiyonu çağıran kişi hatayı açıkça kontrol eder. Bu bazen fazla satır yazdırır ama üretim sistemlerinde “hata nereden geldi?” dedektifliğini azaltır.</p>

<table>
  <thead>
    <tr>
      <th>Hata yaklaşımı</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>C hata kodu</td>
      <td>Basit, düşük maliyetli</td>
      <td>Kontrol unutulabilir</td>
    </tr>
    <tr>
      <td>C++ exception</td>
      <td>Akışı temiz tutabilir</td>
      <td>Gizli kontrol akışı oluşturur</td>
    </tr>
    <tr>
      <td>Go error değeri</td>
      <td>Açık ve okunabilir</td>
      <td>Daha fazla tekrar üretir</td>
    </tr>
  </tbody>
</table>

<p>Go’nun C++’tan en belirgin ayrımlarından biri kalıtımı reddetmesidir. C++’ta <code class="language-plaintext highlighter-rouge">class Dog : public Animal</code> gibi hiyerarşiler kurulabilir. Go’da ise “bir şeyin ne olduğundan çok, ne yapabildiği” önemlidir. Interface’ler örtük uygulanır; bir struct gerekli metotlara sahipse o interface’i sağlamış olur.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">Speaker</span> <span class="k">interface</span> <span class="p">{</span>
    <span class="n">Speak</span><span class="p">()</span> <span class="kt">string</span>
<span class="p">}</span>

<span class="k">type</span> <span class="n">Robot</span> <span class="k">struct</span><span class="p">{}</span>

<span class="k">func</span> <span class="p">(</span><span class="n">r</span> <span class="n">Robot</span><span class="p">)</span> <span class="n">Speak</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="k">return</span> <span class="s">"bip bip"</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Robot</code>, açıkça <code class="language-plaintext highlighter-rouge">Speaker</code> olduğunu ilan etmez; <code class="language-plaintext highlighter-rouge">Speak()</code> metoduna sahip olduğu için Speaker gibi kullanılabilir. Bu yaklaşım ördek tiplemesine benzer ama statiktir: Eğer $Nesne \rightarrow Davranış$ eşleşmesi derleme zamanında tutarlıysa kod güvenle çalışır.</p>

<p>Bellek tarafında C/C++ daha keskin bıçaktır. <code class="language-plaintext highlighter-rouge">malloc/free</code>, <code class="language-plaintext highlighter-rouge">new/delete</code>, pointer aritmetiği ve yaşam süresi yönetimi güçlüdür; fakat dangling pointer, double free ve memory leak gibi canavarları da davet eder. Go pointer kullanır ama pointer aritmetiği sunmaz; ayrıca garbage collector ile çoğu yaşam süresi sorununu üstlenir. Bedeli, bazı durumlarda GC gecikmesi ve C kadar deterministik bellek kontrolü sağlayamamasıdır.</p>

<p>Eşzamanlılıkta Go’nun yıldızı parlar. C++ thread tabanlı düşünürken Go “goroutine” ile çok daha hafif görevler oluşturur. Channel yapısı, veriyi paylaşarak iletişim kurmak yerine iletişim kurarak veriyi paylaşma fikrini teşvik eder. Bu, CSP modeline dayanır ve kabaca $iş\ parçacığı \neq mantıksal\ görev$ ayrımını pratikleştirir.</p>

<p>Sonuç olarak Go, C/C++’ın mirasını tamamen reddetmez; sözdizimsel olarak onlardan esinlenir. Ancak felsefi olarak daha az özellik, daha net araçlar ve daha okunabilir ekip kodu ister. Eğer C/C++ bir laboratuvar dolusu gelişmiş cihazsa, Go düzenli bir atölyedir: Her şey elinizin altındadır, bazı çılgın deneyler yasaktır ama işinizi hızlı, temiz ve güvenli biçimde bitirme ihtimaliniz yüksektir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Go" /><category term="C++" /><category term="Programlama Dilleri" /><category term="Sözdizimi" /><summary type="html"><![CDATA[Go, yani Gopher’ların neşeli dünyası, ilk bakışta C ailesinden gelmiş gibi görünür: süslü parantezler, tipler, fonksiyonlar… Fakat birkaç satır yazınca anlarız ki Go’nun derdi yalnızca kod çalıştırmak değil, geliştiriciyi karmaşadan korumaktır. C/C++ bize büyük güç ve büyük sorumluluk verirken, Go daha çok “ekipçe okunabilir, hızlı derlenebilir, güvenli varsayılanlara sahip yazılım” fikrini merkeze alır.]]></summary></entry><entry><title type="html">Go’da Karar Vermek ve Dönmek: if-else ile for Döngüsünün Akış Yönetimi</title><link href="https://sonsuzus.github.io/posts/goda-karar-vermek-ve-donmek-if-else-ile-for-dongusunun-akis-yonetimi/" rel="alternate" type="text/html" title="Go’da Karar Vermek ve Dönmek: if-else ile for Döngüsünün Akış Yönetimi" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/goda-karar-vermek-ve-donmek-if-else-ile-for-dongusunun-akis-yonetimi</id><content type="html" xml:base="https://sonsuzus.github.io/posts/goda-karar-vermek-ve-donmek-if-else-ile-for-dongusunun-akis-yonetimi/"><![CDATA[<p>Bir programı ilginç yapan şey yalnızca komutları sırayla çalıştırması değil, koşullara göre karar verebilmesi ve gerektiğinde aynı işi tekrar tekrar yapabilmesidir. Go dilinde bu akış yönetiminin iki ana kahramanı vardır: karar almak için <code class="language-plaintext highlighter-rouge">if-else</code>, tekrar etmek için ise neredeyse her role bürünen <code class="language-plaintext highlighter-rouge">for</code> döngüsü.
``</p>

<h2 id="akış-yönetimi-neden-önemlidir">Akış yönetimi neden önemlidir?</h2>

<p>Bilgisayar programını küçük bir karar makinesi gibi düşünebiliriz. Elimizde bir durum, yani değişkenler vardır; program bu durumlara bakar ve hangi yoldan ilerleyeceğine karar verir. Matematiksel olarak bir koşul çoğu zaman şu mantıksal ifadeye benzer:</p>

<p>$sonuc = (yas \ge 18) \land (puan &gt; 50)$</p>

<p>Burada ifade <code class="language-plaintext highlighter-rouge">true</code> ise bir blok, <code class="language-plaintext highlighter-rouge">false</code> ise başka bir blok çalışır. Go’da koşullar parantez içine alınmaz; bu, dilin sade ve okunabilir olma tercihidir.</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">puan</span> <span class="o">:=</span> <span class="m">72</span>

    <span class="k">if</span> <span class="n">puan</span> <span class="o">&gt;=</span> <span class="m">85</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">"Harika!"</span><span class="p">)</span>
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="n">puan</span> <span class="o">&gt;=</span> <span class="m">50</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">"Geçtin, ama kahveye devam."</span><span class="p">)</span>
    <span class="p">}</span> <span class="k">else</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">"Tekrar deneme zamanı."</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu örnekte program, <code class="language-plaintext highlighter-rouge">puan</code> değerine göre yalnızca bir yolu seçer. <code class="language-plaintext highlighter-rouge">if</code> ilk doğru koşulu yakaladığında devamındaki <code class="language-plaintext highlighter-rouge">else if</code> bloklarına bakmaz. Yani akış, gereksiz kontrol yapmadan ilerler.</p>

<table>
  <thead>
    <tr>
      <th>Yapı</th>
      <th>Ne zaman kullanılır?</th>
      <th>Go’daki not</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">if</code></td>
      <td>Tek bir koşul kontrol edilecekse</td>
      <td>Koşul parantezsiz yazılır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">else if</code></td>
      <td>Birden fazla alternatif varsa</td>
      <td>Sıralama önemlidir</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">else</code></td>
      <td>Hiçbir koşul sağlanmazsa</td>
      <td>Varsayılan yol gibidir</td>
    </tr>
  </tbody>
</table>

<h2 id="if-içinde-kısa-değişken-tanımlama">if içinde kısa değişken tanımlama</h2>

<p>Go’nun tatlı özelliklerinden biri, <code class="language-plaintext highlighter-rouge">if</code> satırında küçük bir hazırlık yapabilmektir. Bu özellikle hata kontrolünde çok görü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="s">"fmt"</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">if</span> <span class="n">sayi</span> <span class="o">:=</span> <span class="m">42</span><span class="p">;</span> <span class="n">sayi</span><span class="o">%</span><span class="m">2</span> <span class="o">==</span> <span class="m">0</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">"Çift sayı:"</span><span class="p">,</span> <span class="n">sayi</span><span class="p">)</span>
    <span class="p">}</span> <span class="k">else</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">"Tek sayı:"</span><span class="p">,</span> <span class="n">sayi</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">sayi</code> yalnızca <code class="language-plaintext highlighter-rouge">if-else</code> bloğunun içinde yaşar. Bu sayede değişkenin kapsamı dar tutulur. Daha az kapsam, daha az kafa karışıklığı demektir.</p>

<h2 id="goda-tek-döngü-for">Go’da tek döngü: for</h2>

<p>Go’da <code class="language-plaintext highlighter-rouge">while</code> veya <code class="language-plaintext highlighter-rouge">do-while</code> anahtar kelimeleri yoktur. İlk bakışta eksiklik gibi görünür, ama <code class="language-plaintext highlighter-rouge">for</code> o kadar esnektir ki hepsinin görevini üstlenir. Klasik kullanım üç parçadan oluşur:</p>

<p>$baslangic \rightarrow kosul \rightarrow guncelleme$</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">toplam</span> <span class="o">:=</span> <span class="m">0</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">toplam</span> <span class="o">+=</span> <span class="n">i</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">"Toplam:"</span><span class="p">,</span> <span class="n">toplam</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kodda <code class="language-plaintext highlighter-rouge">i</code> değeri 1’den 5’e kadar ilerler ve toplam hesaplanır. Döngünün çalışma maliyetini kabaca $O(n)$ olarak düşünebiliriz; çünkü tekrar sayısı, veri boyutu ile doğru orantılıdır.</p>

<table>
  <thead>
    <tr>
      <th>Döngü biçimi</th>
      <th>Örnek</th>
      <th>Benzer olduğu yapı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Klasik <code class="language-plaintext highlighter-rouge">for</code></td>
      <td><code class="language-plaintext highlighter-rouge">for i := 0; i &lt; n; i++</code></td>
      <td>C tarzı döngü</td>
    </tr>
    <tr>
      <td>Koşullu <code class="language-plaintext highlighter-rouge">for</code></td>
      <td><code class="language-plaintext highlighter-rouge">for x &lt; 10</code></td>
      <td><code class="language-plaintext highlighter-rouge">while</code></td>
    </tr>
    <tr>
      <td>Sonsuz <code class="language-plaintext highlighter-rouge">for</code></td>
      <td><code class="language-plaintext highlighter-rouge">for {}</code></td>
      <td>Sonsuz döngü</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">range</code> ile <code class="language-plaintext highlighter-rouge">for</code></td>
      <td><code class="language-plaintext highlighter-rouge">for i, v := range liste</code></td>
      <td>Koleksiyon gezme</td>
    </tr>
  </tbody>
</table>

<h2 id="while-gibi-for-kullanımı">while gibi for kullanımı</h2>

<p>Go’da sadece koşul yazarak <code class="language-plaintext highlighter-rouge">while</code> benzeri bir döngü oluşturabiliriz.</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">enerji</span> <span class="o">:=</span> <span class="m">3</span>

    <span class="k">for</span> <span class="n">enerji</span> <span class="o">&gt;</span> <span class="m">0</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">"Kod yazılıyor... enerji:"</span><span class="p">,</span> <span class="n">enerji</span><span class="p">)</span>
        <span class="n">enerji</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">"Mola zamanı!"</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu tarz, koşulun ne zaman bozulacağını dışarıdan kontrol etmek istediğimiz durumlarda okunaklıdır.</p>

<h2 id="range-ile-koleksiyon-gezmek">range ile koleksiyon gezmek</h2>

<p>Diziler, dilimler, map’ler ve string’ler üzerinde dolaşmak için <code class="language-plaintext highlighter-rouge">range</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="s">"fmt"</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">diller</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"Go"</span><span class="p">,</span> <span class="s">"Python"</span><span class="p">,</span> <span class="s">"Rust"</span><span class="p">}</span>

    <span class="k">for</span> <span class="n">indeks</span><span class="p">,</span> <span class="n">dil</span> <span class="o">:=</span> <span class="k">range</span> <span class="n">diller</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">indeks</span><span class="p">,</span> <span class="n">dil</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">range</code>, her turda indeks ve değeri verir. Eğer indekse ihtiyacımız yoksa <code class="language-plaintext highlighter-rouge">_</code> ile görmezden gelebiliriz. Bu, Go’nun açık niyetli kod yazma felsefesine uygundur.</p>

<h2 id="break-ve-continue-döngünün-trafik-levhaları">break ve continue: döngünün trafik levhaları</h2>

<p><code class="language-plaintext highlighter-rouge">break</code> döngüyü tamamen bitirir, <code class="language-plaintext highlighter-rouge">continue</code> ise mevcut turu atlayıp sonraki tura geçer.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><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">10</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span> <span class="p">{</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="m">7</span> <span class="p">{</span>
        <span class="k">break</span>
    <span class="p">}</span>
    <span class="k">if</span> <span class="n">i</span><span class="o">%</span><span class="m">2</span> <span class="o">==</span> <span class="m">0</span> <span class="p">{</span>
        <span class="k">continue</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">i</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu kod 7’ye gelince durur, çift sayıları ise yazdırmadan geçer. Yani çıktı yalnızca 1, 3 ve 5 olur.</p>

<p>Özetle Go’da akış yönetimi sade ama güçlüdür. <code class="language-plaintext highlighter-rouge">if-else</code> programın karar mekanizmasını kurar; <code class="language-plaintext highlighter-rouge">for</code> ise tekrar eden işleri tek bir esnek yapı altında toplar. Bu iki aracı iyi kavramak, Go’da okunabilir ve kontrollü programlar yazmanın temelidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="go" /><category term="kontrol-yapıları" /><category term="for-döngüsü" /><summary type="html"><![CDATA[Bir programı ilginç yapan şey yalnızca komutları sırayla çalıştırması değil, koşullara göre karar verebilmesi ve gerektiğinde aynı işi tekrar tekrar yapabilmesidir. Go dilinde bu akış yönetiminin iki ana kahramanı vardır: karar almak için if-else, tekrar etmek için ise neredeyse her role bürünen for döngüsü.]]></summary></entry><entry><title type="html">İşaretçiler ve Bellek Modeli: Go’da Güvenli Adreslerle Dans</title><link href="https://sonsuzus.github.io/posts/isaretciler-ve-bellek-modeli-goda-guvenli-adreslerle-dans/" rel="alternate" type="text/html" title="İşaretçiler ve Bellek Modeli: Go’da Güvenli Adreslerle Dans" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/isaretciler-ve-bellek-modeli-goda-guvenli-adreslerle-dans</id><content type="html" xml:base="https://sonsuzus.github.io/posts/isaretciler-ve-bellek-modeli-goda-guvenli-adreslerle-dans/"><![CDATA[<p>Programlama dünyasında işaretçiler, belleğin haritasını elinize alıp “şu adrese git, oradaki değeri getir” demenin yoludur. C ve C++ tarafında bu harita bazen hazineye, bazen de mayın tarlasına çıkar; Go ise aynı fikri daha güvenli korkuluklarla sunar. Yani adresleri görebiliriz, değerleri dolaylı yoldan değiştirebiliriz ama rastgele bellek aritmetiğiyle sistemi yakmamıza izin verilmez.
``</p>

<p>Belleği kabaca büyük bir apartman gibi düşünebiliriz. Her dairenin bir numarası, yani adresi vardır. Bir değişken de bu dairelerden birinde oturan veridir. Matematiksel olarak bellek, adreslerden değerlere giden bir fonksiyon gibi düşünülebilir: $M: A \rightarrow V$. Burada $A$ adres kümesini, $V$ ise değerleri temsil eder. Bir işaretçi ise doğrudan değeri değil, o değerin yaşadığı adresi tutar.</p>

<p>Go’da bir değişkenin adresini almak için <code class="language-plaintext highlighter-rouge">&amp;</code>, işaretçinin gösterdiği değere erişmek için <code class="language-plaintext highlighter-rouge">*</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="s">"fmt"</span>

<span class="k">func</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">x</span> <span class="o">:=</span> <span class="m">42</span>
    <span class="n">p</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="n">x</span> <span class="c">// x değişkeninin adresini tutar</span>

    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">x</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">p</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">*</span><span class="n">p</span><span class="p">)</span>

    <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="m">100</span> <span class="c">// p üzerinden x değerini değiştirir</span>
    <span class="n">fmt</span><span class="o">.</span><span class="n">Println</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu örnekte <code class="language-plaintext highlighter-rouge">p</code>, <code class="language-plaintext highlighter-rouge">x</code> değişkeninin adresini saklar. <code class="language-plaintext highlighter-rouge">*p = 100</code> dediğimizde “p’nin gösterdiği adresteki değeri 100 yap” deriz. Sonuçta değişen şey <code class="language-plaintext highlighter-rouge">p</code> değil, <code class="language-plaintext highlighter-rouge">x</code> olur. İşte işaretçilerin gücü burada başlar: veriyi kopyalamadan, aynı bellek konumuna erişmek.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Anlamı</th>
      <th>Go’daki Operatör</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Değer</td>
      <td>Bellekte saklanan gerçek veri</td>
      <td><code class="language-plaintext highlighter-rouge">x</code></td>
    </tr>
    <tr>
      <td>Adres</td>
      <td>Verinin bellekteki konumu</td>
      <td><code class="language-plaintext highlighter-rouge">&amp;x</code></td>
    </tr>
    <tr>
      <td>İşaretçi</td>
      <td>Adresi tutan değişken</td>
      <td><code class="language-plaintext highlighter-rouge">p := &amp;x</code></td>
    </tr>
    <tr>
      <td>Dereference</td>
      <td>Adresteki değere erişme</td>
      <td><code class="language-plaintext highlighter-rouge">*p</code></td>
    </tr>
  </tbody>
</table>

<p>Peki bu neden önemli? Çünkü büyük veri yapıları kopyalanmak yerine adres üzerinden taşınabilir. Diyelim ki elimizde büyük bir <code class="language-plaintext highlighter-rouge">struct</code> var. Bunu fonksiyona değer olarak verirsek kopya oluşur. İşaretçiyle verirsek aynı nesne üzerinde çalışırız.</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="n">User</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">ID</span>    <span class="kt">int</span>
    <span class="n">Score</span> <span class="kt">int</span>
<span class="p">}</span>

<span class="k">func</span> <span class="n">increaseScore</span><span class="p">(</span><span class="n">u</span> <span class="o">*</span><span class="n">User</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">u</span><span class="o">.</span><span class="n">Score</span> <span class="o">+=</span> <span class="m">10</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">user</span> <span class="o">:=</span> <span class="n">User</span><span class="p">{</span><span class="n">ID</span><span class="o">:</span> <span class="m">1</span><span class="p">,</span> <span class="n">Score</span><span class="o">:</span> <span class="m">50</span><span class="p">}</span>
    <span class="n">increaseScore</span><span class="p">(</span><span class="o">&amp;</span><span class="n">user</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">user</span><span class="o">.</span><span class="n">Score</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">increaseScore</code> fonksiyonu <code class="language-plaintext highlighter-rouge">*User</code> alır. Yani bir kullanıcı kopyası değil, kullanıcının adresi fonksiyona gider. Go, <code class="language-plaintext highlighter-rouge">u.Score</code> yazımına izin vererek <code class="language-plaintext highlighter-rouge">(*u).Score</code> ifadesini bizim için sadeleştirir. Küçük ama tatlı bir ergonomi hediyesi!</p>

<p>Go’nun bellek modeli stack ve heap kavramlarıyla çalışır. Stack, fonksiyon çağrıları için hızlı ve düzenli bir alandır. Heap ise yaşam süresi daha belirsiz olan nesneler için kullanılır. Derleyici, escape analysis denen analizle bir değişkenin fonksiyon dışına “kaçıp kaçmadığını” inceler. Eğer kaçıyorsa heap’e taşınabilir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Stack</th>
      <th>Heap</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Hız</td>
      <td>Çok hızlı</td>
      <td>Görece yavaş</td>
    </tr>
    <tr>
      <td>Yönetim</td>
      <td>Otomatik, fonksiyon bitince temizlenir</td>
      <td>Garbage collector tarafından izlenir</td>
    </tr>
    <tr>
      <td>Kullanım</td>
      <td>Yerel ve kısa ömürlü veriler</td>
      <td>Paylaşılan veya uzun ömürlü veriler</td>
    </tr>
    <tr>
      <td>Go kararı</td>
      <td>Derleyici analiz eder</td>
      <td>Derleyici ve GC birlikte yönetir</td>
    </tr>
  </tbody>
</table>

<p>Örneğin bir fonksiyon yerel değişkenin adresini döndürürse, Go bunu tehlikeli kabul edip çökmez; derleyici değişkeni heap’e taşıyabilir:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">func</span> <span class="n">newCounter</span><span class="p">()</span> <span class="o">*</span><span class="kt">int</span> <span class="p">{</span>
    <span class="n">count</span> <span class="o">:=</span> <span class="m">0</span>
    <span class="k">return</span> <span class="o">&amp;</span><span class="n">count</span>
<span class="p">}</span>
</code></pre></div></div>

<p>C dilinde benzer bir durum büyük bir probleme dönüşebilirken Go, yaşam süresini analiz eder. Çünkü Go’da amaç, işaretçilerin performans avantajını verirken “dangling pointer” gibi klasik hataları azaltmaktır.</p>

<p>Garbage collector, heap üzerindeki artık erişilemeyen nesneleri temizleyen arka plan görevlisidir. Basitçe köklerden, yani global değişkenlerden, stack’teki referanslardan ve aktif goroutine’lerden başlar; erişilebilen nesneleri işaretler. Erişilemeyenler çöp kabul edilir. Bunu grafik gibi düşünebiliriz: Eğer bir nesneye giden yol yoksa, $reachable(obj) = false$ olur ve temizlik adayıdır.</p>

<p>Go’nun işaretçileri güvenlidir çünkü pointer arithmetic desteklenmez. Yani <code class="language-plaintext highlighter-rouge">p + 1</code> diyerek keyfi adrese zıplayamayız. Bu, bellek modelini daha öngörülebilir yapar. Elbette <code class="language-plaintext highlighter-rouge">unsafe</code> paketiyle bu sınırlar aşılabilir; fakat adı üstünde, orası emniyet kemerini çıkarıp viraja hızlı girmek gibidir.</p>

<p>Sonuç olarak Go’da işaretçiler, belleği doğrudan yönetmenin kontrollü bir yoludur. Adresleri kullanırız, kopyaları azaltırız, fonksiyonlar arasında veriyi etkili biçimde paylaşırız. Arka planda derleyicinin escape analysis mekanizması ve garbage collector ikilisi, çoğu bellek temizliği yükünü bizden alır. Kısacası Go, işaretçileri bir testere gibi değil, güvenlik kilitli bir İsviçre çakısı gibi sunar: güçlü, pratik ve dikkatli kullanıldığında oldukça keyifli.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="Go" /><category term="Pointers" /><category term="Garbage Collector" /><category term="Bellek Yönetimi" /><summary type="html"><![CDATA[Programlama dünyasında işaretçiler, belleğin haritasını elinize alıp “şu adrese git, oradaki değeri getir” demenin yoludur. C ve C++ tarafında bu harita bazen hazineye, bazen de mayın tarlasına çıkar; Go ise aynı fikri daha güvenli korkuluklarla sunar. Yani adresleri görebiliriz, değerleri dolaylı yoldan değiştirebiliriz ama rastgele bellek aritmetiğiyle sistemi yakmamıza izin verilmez.]]></summary></entry><entry><title type="html">Kural Tabanlı Botlar ve Gerçek Dünya Uygulamaları</title><link href="https://sonsuzus.github.io/posts/kural-tabanli-botlar-ve-gercek-dunya-uygulamalari/" rel="alternate" type="text/html" title="Kural Tabanlı Botlar ve Gerçek Dünya Uygulamaları" /><published>2026-07-23T00:00:00+00:00</published><updated>2026-07-23T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/kural-tabanli-botlar-ve-gercek-dunya-uygulamalari</id><content type="html" xml:base="https://sonsuzus.github.io/posts/kural-tabanli-botlar-ve-gercek-dunya-uygulamalari/"><![CDATA[<p>Kural tabanlı botlar, yapay zekanın sihirli değneği gibi görünmeyebilir; ama gerçek dünyada birçok otomasyonun sessiz kahramanıdır. Bir metni okuyup sınıflandıran müşteri destek botu, başvuru formundaki riskleri işaretleyen karar destek sistemi veya moderasyon kuyruğuna mesaj düşüren filtreler çoğu zaman öğrenilmiş devasa modellerden önce mantık, koşul ve iyi tasarlanmış kurallar üzerine kurulur.</p>

<p>``</p>

<p>Temel fikir oldukça nettir: <strong>Eğer belirli koşullar sağlanıyorsa, belirli bir eylem çalıştırılır.</strong> Bu yapı programlamadaki <code class="language-plaintext highlighter-rouge">if-else</code> mantığının daha sistematik hâlidir. Bir kuralı basitçe $kosul -&gt; eylem$ şeklinde düşünebiliriz. Örneğin bir mesajda hem acil kelimesi geçiyor hem de sipariş numarası bulunuyorsa, bot bunu öncelikli destek talebi olarak etiketleyebilir.</p>

<p>Kural tabanlı sistemlerin gücü, teorik olarak üç ana kavrama dayanır: sembolik temsil, mantıksal çıkarım ve karar akışı. Sembolik temsil, gerçek dünyadaki karmaşık ifadeleri daha işlenebilir parçalara ayırır. Mesela kullanıcının yazdığı metin; kelimeler, niyetler, anahtar ifadeler ve sayısal sinyaller olarak temsil edilir. Mantıksal çıkarım ise bu sinyallerden sonuç üretir: $skor = w1 * aciliyet + w2 * negatiflik - w3 * belirsizlik$ gibi basit bir formül bile karar destek sistemlerinde çok işe yarar.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
      <th>Uygun Senaryo</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kural tabanlı</td>
      <td>Açıklanabilir, hızlı, kontrol edilebilir</td>
      <td>Kurallar çoğalınca bakım zorlaşır</td>
      <td>SSS botları, filtreleme, iş akışı</td>
    </tr>
    <tr>
      <td>Makine öğrenmesi</td>
      <td>Örüntüleri veriden öğrenir</td>
      <td>Veri ister, açıklaması zor olabilir</td>
      <td>Büyük ölçekli sınıflandırma</td>
    </tr>
    <tr>
      <td>Hibrit sistem</td>
      <td>Hem kontrol hem esneklik sağlar</td>
      <td>Tasarım karmaşıktır</td>
      <td>Kurumsal karar destek sistemleri</td>
    </tr>
  </tbody>
</table>

<p>Metin işleyen bir bot geliştirirken ilk adım, metni normalize etmektir. Büyük-küçük harf farkı, noktalama işaretleri ve gereksiz boşluklar kararları bozabilir. Ardından anahtar kelime, desen veya bağlam sinyalleri çıkarılır. Burada düzenli ifadeler, sözlükler ve puanlama fonksiyonları devreye girer.</p>

<p>Aşağıdaki örnek, müşteri destek mesajlarını basit kurallarla sınıflandırır. Kodun amacı; metindeki sinyalleri analiz edip destek ekibine hangi kuyruğa yönlendirme yapılacağını göstermektir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">re</span>

<span class="n">RULES</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">{</span>
        <span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Acil sipariş problemi</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">keywords</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span><span class="sh">'</span><span class="s">acil</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">gelmedi</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">kargo</span><span class="sh">'</span><span class="p">],</span>
        <span class="sh">'</span><span class="s">queue</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">oncelikli_destek</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">score</span><span class="sh">'</span><span class="p">:</span> <span class="mi">8</span>
    <span class="p">},</span>
    <span class="p">{</span>
        <span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">İade talebi</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">keywords</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span><span class="sh">'</span><span class="s">iade</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">geri göndermek</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">memnun değilim</span><span class="sh">'</span><span class="p">],</span>
        <span class="sh">'</span><span class="s">queue</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">iade_ekibi</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">score</span><span class="sh">'</span><span class="p">:</span> <span class="mi">6</span>
    <span class="p">},</span>
    <span class="p">{</span>
        <span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Fatura sorunu</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">keywords</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span><span class="sh">'</span><span class="s">fatura</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">vergi</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">adres</span><span class="sh">'</span><span class="p">],</span>
        <span class="sh">'</span><span class="s">queue</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">muhasebe</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">score</span><span class="sh">'</span><span class="p">:</span> <span class="mi">5</span>
    <span class="p">}</span>
<span class="p">]</span>

<span class="k">def</span> <span class="nf">normalize</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">re</span><span class="p">.</span><span class="nf">sub</span><span class="p">(</span><span class="sa">r</span><span class="sh">'</span><span class="s">\s+</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s"> </span><span class="sh">'</span><span class="p">,</span> <span class="n">text</span><span class="p">.</span><span class="nf">lower</span><span class="p">()).</span><span class="nf">strip</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">classify</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
    <span class="n">text</span> <span class="o">=</span> <span class="nf">normalize</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
    <span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">RULES</span><span class="p">:</span>
        <span class="n">hit_count</span> <span class="o">=</span> <span class="nf">sum</span><span class="p">(</span><span class="mi">1</span> <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">rule</span><span class="p">[</span><span class="sh">'</span><span class="s">keywords</span><span class="sh">'</span><span class="p">]</span> <span class="k">if</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">text</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">hit_count</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">results</span><span class="p">.</span><span class="nf">append</span><span class="p">({</span>
                <span class="sh">'</span><span class="s">rule</span><span class="sh">'</span><span class="p">:</span> <span class="n">rule</span><span class="p">[</span><span class="sh">'</span><span class="s">name</span><span class="sh">'</span><span class="p">],</span>
                <span class="sh">'</span><span class="s">queue</span><span class="sh">'</span><span class="p">:</span> <span class="n">rule</span><span class="p">[</span><span class="sh">'</span><span class="s">queue</span><span class="sh">'</span><span class="p">],</span>
                <span class="sh">'</span><span class="s">final_score</span><span class="sh">'</span><span class="p">:</span> <span class="n">rule</span><span class="p">[</span><span class="sh">'</span><span class="s">score</span><span class="sh">'</span><span class="p">]</span> <span class="o">+</span> <span class="n">hit_count</span>
            <span class="p">})</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">results</span><span class="p">:</span>
        <span class="k">return</span> <span class="p">{</span><span class="sh">'</span><span class="s">queue</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">genel_destek</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">reason</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Eşleşen kural yok</span><span class="sh">'</span><span class="p">}</span>

    <span class="k">return</span> <span class="nf">max</span><span class="p">(</span><span class="n">results</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">item</span><span class="p">:</span> <span class="n">item</span><span class="p">[</span><span class="sh">'</span><span class="s">final_score</span><span class="sh">'</span><span class="p">])</span>

<span class="nf">print</span><span class="p">(</span><span class="nf">classify</span><span class="p">(</span><span class="sh">'</span><span class="s">Kargom gelmedi, acil destek istiyorum.</span><span class="sh">'</span><span class="p">))</span>
</code></pre></div></div>

<p>Bu örnekte bot, makine öğrenmesi yapmıyor; fakat kararını açıklayabiliyor. Neden öncelikli destek kuyruğu seçildi? Çünkü metinde acil ve kargo gibi sinyaller bulundu. Gerçek dünyada bu açıklanabilirlik çok değerlidir. Özellikle finans, sağlık, hukuk ve insan kaynakları gibi alanlarda sistemin sadece karar vermesi değil, kararın gerekçesini sunması da gerekir.</p>

<table>
  <thead>
    <tr>
      <th>Kural Türü</th>
      <th>Örnek</th>
      <th>Kullanım Amacı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Anahtar kelime</td>
      <td>Şifre, ödeme, iade</td>
      <td>Hızlı niyet yakalama</td>
    </tr>
    <tr>
      <td>Desen tabanlı</td>
      <td>Sipariş no: 12345</td>
      <td>Yapısal bilgi çıkarma</td>
    </tr>
    <tr>
      <td>Puanlama</td>
      <td>Risk skoru &gt; 70</td>
      <td>Önceliklendirme</td>
    </tr>
    <tr>
      <td>Engelleme</td>
      <td>Yasaklı kelime listesi</td>
      <td>Moderasyon</td>
    </tr>
  </tbody>
</table>

<p>Ancak kural tabanlı botların karanlık tarafı da vardır: kural patlaması. Her yeni istisna için yeni bir kural yazıldığında sistem bir süre sonra spagettiye dönebilir. Bu yüzden kurallar kategorilere ayrılmalı, öncelik değerleri net tanımlanmalı ve çakışma yönetimi yapılmalıdır. Örneğin iki kural aynı anda çalışıyorsa en yüksek skor mu seçilecek, yoksa kritik etiket her zaman üstün mü gelecek? Bu kararlar baştan tasarlanmalıdır.</p>

<p>İyi bir mimaride kurallar kodun içine gömülmek yerine JSON, YAML veya veritabanında saklanabilir. Böylece yazılımcı olmayan alan uzmanları da kuralları güncelleyebilir. Ayrıca her karar için günlük kaydı tutulmalıdır: hangi metin geldi, hangi kurallar tetiklendi, sonuç ne oldu? Bu kayıtlar sistemin iyileştirilmesi için altın madeni gibidir.</p>

<p>Sonuç olarak kural tabanlı botlar, teorik mantık ile pratik yazılım mühendisliğinin eğlenceli buluşma noktasıdır. Doğru normalize edilmiş metin, iyi tasarlanmış koşullar, puanlama mantığı ve açıklanabilir karar akışı birleştiğinde küçük ama güçlü otomasyonlar ortaya çıkar. Büyük yapay zeka modellerinin çağında bile, bazen en iyi çözüm hâlâ şudur: açık, okunabilir ve test edilebilir bir kural.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="kural tabanlı botlar" /><category term="doğal dil işleme" /><category term="karar destek sistemleri" /><summary type="html"><![CDATA[Kural tabanlı botlar, yapay zekanın sihirli değneği gibi görünmeyebilir; ama gerçek dünyada birçok otomasyonun sessiz kahramanıdır. Bir metni okuyup sınıflandıran müşteri destek botu, başvuru formundaki riskleri işaretleyen karar destek sistemi veya moderasyon kuyruğuna mesaj düşüren filtreler çoğu zaman öğrenilmiş devasa modellerden önce mantık, koşul ve iyi tasarlanmış kurallar üzerine kurulur.]]></summary></entry><entry><title type="html">ext4 Günlükleme Mekanizmasını dd ve hexdump ile Canlı İzlemek</title><link href="https://sonsuzus.github.io/posts/ext4-gunlukleme-mekanizmasini-dd-ve-hexdump-ile-canli-izlemek/" rel="alternate" type="text/html" title="ext4 Günlükleme Mekanizmasını dd ve hexdump ile Canlı İzlemek" /><published>2026-07-22T00:00:00+00:00</published><updated>2026-07-22T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/ext4-gunlukleme-mekanizmasini-dd-ve-hexdump-ile-canli-izlemek</id><content type="html" xml:base="https://sonsuzus.github.io/posts/ext4-gunlukleme-mekanizmasini-dd-ve-hexdump-ile-canli-izlemek/"><![CDATA[<p>ext4 dosya sisteminde bir dosya yazdığınızda verinin diske “hop diye” gitmediğini bilmek, Linux’un perde arkasını anlamak için harika bir başlangıçtır. Bu yazıda güvenli bir loop imaj üzerinde ext4 günlük bölgesini bulup, yazma işlemi sırasında <code class="language-plaintext highlighter-rouge">dd</code> ve <code class="language-plaintext highlighter-rouge">hexdump</code> ile anlık izleyen küçük bir Bash betiği hazırlayacağız. Gerçek diskinize dokunmadan, dosya sisteminin kalp atışlarını dinleyeceğiz.
``</p>

<p>ext4’ün günlükleme mekanizması, özellikle sistem çökmesi veya elektrik kesintisi gibi durumlarda dosya sisteminin tutarlı kalmasını sağlar. Basit fikir şudur: Kritik meta veri değişiklikleri önce “journal” denen özel bir alana yazılır, ardından asıl konumlarına uygulanır. Böylece sistem yarıda kesilirse ext4, günlüğe bakarak işlemi tamamlayabilir veya geri alabilir.</p>

<p>Teorik olarak bunu küçük bir işlem sırası gibi düşünebiliriz:</p>

\[T = \{metadata\ write, commit\ block, checkpoint\}\]

<p>Burada <code class="language-plaintext highlighter-rouge">commit block</code>, “bu işlem grubu tamamlandı” damgası gibidir. ext4 varsayılan olarak genellikle <code class="language-plaintext highlighter-rouge">data=ordered</code> kipinde çalışır: dosya verisi asıl yerine yazılır, meta veri ise journal üzerinden güvenceye alınır.</p>

<table>
  <thead>
    <tr>
      <th>Kip</th>
      <th style="text-align: right">Veri journal’a yazılır mı?</th>
      <th style="text-align: right">Meta veri journal’a yazılır mı?</th>
      <th style="text-align: right">Performans</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">data=journal</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Daha yavaş, daha güvenli</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">data=ordered</code></td>
      <td style="text-align: right">Hayır, önce diske gider</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Dengeli</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">data=writeback</code></td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Hızlı, sıralama garantisi zayıf</td>
    </tr>
  </tbody>
</table>

<p>Journal alanı ext4 içinde çoğunlukla özel bir inode olarak tutulur: inode <code class="language-plaintext highlighter-rouge">8</code>. Biz bu inode’un fiziksel bloklarını <code class="language-plaintext highlighter-rouge">debugfs</code> ile bulacağız. Bir blok numarası $P$, blok boyutu $B$ ise byte cinsinden konum:</p>

\[offset = P \times B\]

<p><code class="language-plaintext highlighter-rouge">dd</code> komutu bu ofsete gidip blokları okuyacak, <code class="language-plaintext highlighter-rouge">hexdump</code> da bize ham içeriği gösterecek.</p>

<p>Önce güvenli bir laboratuvar oluşturalım:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">truncate</span> <span class="nt">-s</span> 256M ext4-lab.img
mkfs.ext4 <span class="nt">-F</span> ext4-lab.img
<span class="nb">mkdir</span> <span class="nt">-p</span> mnt-lab
<span class="nb">sudo </span>mount <span class="nt">-o</span> loop ext4-lab.img mnt-lab
</code></pre></div></div>

<p>Şimdi izleme betiğimiz gelsin. Bu betik imaj dosyasından blok boyutunu öğrenir, journal inode’unun ilk extent’ini bulur ve belirli aralıklarla o bölgeden veri okuyup hexadecimal biçimde gösterir.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="nb">set</span> <span class="nt">-euo</span> pipefail

<span class="nv">IMG</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">1</span><span class="k">:-</span><span class="nv">ext4</span><span class="p">-lab.img</span><span class="k">}</span><span class="s2">"</span>
<span class="nv">BLOCKS_TO_READ</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">2</span><span class="k">:-</span><span class="nv">4</span><span class="k">}</span><span class="s2">"</span>
<span class="nv">INTERVAL</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">3</span><span class="k">:-</span><span class="nv">1</span><span class="k">}</span><span class="s2">"</span>

<span class="k">if</span> <span class="o">[[</span> <span class="o">!</span> <span class="nt">-f</span> <span class="s2">"</span><span class="nv">$IMG</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"İmaj bulunamadı: </span><span class="nv">$IMG</span><span class="s2">"</span> <span class="o">&gt;</span>&amp;2
  <span class="nb">exit </span>1
<span class="k">fi

</span><span class="nv">BS</span><span class="o">=</span><span class="si">$(</span>dumpe2fs <span class="nt">-h</span> <span class="s2">"</span><span class="nv">$IMG</span><span class="s2">"</span> 2&gt;/dev/null | <span class="nb">awk</span> <span class="nt">-F</span>: <span class="s1">'/Block size/ {gsub(/ /,"",$2); print $2}'</span><span class="si">)</span>

<span class="nv">JOURNAL_RANGE</span><span class="o">=</span><span class="si">$(</span>debugfs <span class="nt">-R</span> <span class="s1">'stat &lt;8&gt;'</span> <span class="s2">"</span><span class="nv">$IMG</span><span class="s2">"</span> 2&gt;/dev/null <span class="se">\</span>
  | <span class="nb">awk</span> <span class="s1">'
    match($0, /\):([0-9]+)-([0-9]+)/, a) { print a[1], a[2]; exit }
    match($0, /\):([0-9]+)/, a) { print a[1], a[1]; exit }
  '</span><span class="si">)</span>

<span class="nv">START_BLOCK</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$JOURNAL_RANGE</span><span class="s2">"</span> | <span class="nb">awk</span> <span class="s1">'{print $1}'</span><span class="si">)</span>
<span class="nv">END_BLOCK</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$JOURNAL_RANGE</span><span class="s2">"</span> | <span class="nb">awk</span> <span class="s1">'{print $2}'</span><span class="si">)</span>

<span class="k">if</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="k">${</span><span class="nv">START_BLOCK</span><span class="k">:-}</span><span class="s2">"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"Journal blokları bulunamadı. debugfs çıktısını kontrol edin."</span> <span class="o">&gt;</span>&amp;2
  <span class="nb">exit </span>1
<span class="k">fi

</span><span class="nv">OFFSET</span><span class="o">=</span><span class="k">$((</span>START_BLOCK <span class="o">*</span> BS<span class="k">))</span>

<span class="nb">printf</span> <span class="s2">"Blok boyutu      : %s byte</span><span class="se">\n</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$BS</span><span class="s2">"</span>
<span class="nb">printf</span> <span class="s2">"Journal başlangıcı: blok %s</span><span class="se">\n</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$START_BLOCK</span><span class="s2">"</span>
<span class="nb">printf</span> <span class="s2">"Journal bitişi    : blok %s</span><span class="se">\n</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$END_BLOCK</span><span class="s2">"</span>
<span class="nb">printf</span> <span class="s2">"Okunan offset     : %s byte</span><span class="se">\n\n</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$OFFSET</span><span class="s2">"</span>

<span class="k">while </span><span class="nb">true</span><span class="p">;</span> <span class="k">do
  </span>clear
  <span class="nb">date
  echo</span> <span class="s2">"Journal bölgesinden </span><span class="nv">$BLOCKS_TO_READ</span><span class="s2"> blok okunuyor..."</span>
  <span class="nb">dd </span><span class="k">if</span><span class="o">=</span><span class="s2">"</span><span class="nv">$IMG</span><span class="s2">"</span> <span class="nv">bs</span><span class="o">=</span><span class="s2">"</span><span class="nv">$BS</span><span class="s2">"</span> <span class="nv">skip</span><span class="o">=</span><span class="s2">"</span><span class="nv">$START_BLOCK</span><span class="s2">"</span> <span class="nv">count</span><span class="o">=</span><span class="s2">"</span><span class="nv">$BLOCKS_TO_READ</span><span class="s2">"</span> <span class="nv">status</span><span class="o">=</span>none <span class="se">\</span>
    | hexdump <span class="nt">-C</span> | <span class="nb">head</span> <span class="nt">-n</span> 40
  <span class="nb">sleep</span> <span class="s2">"</span><span class="nv">$INTERVAL</span><span class="s2">"</span>
<span class="k">done</span>
</code></pre></div></div>

<p>Kaydedip çalıştırın:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">chmod</span> +x watch-ext4-journal.sh
./watch-ext4-journal.sh ext4-lab.img 8 1
</code></pre></div></div>

<p>Başka bir terminalde dosya sistemine yazma yapalım:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>i <span class="k">in</span> <span class="o">{</span>1..20<span class="o">}</span><span class="p">;</span> <span class="k">do
  </span><span class="nb">sudo dd </span><span class="k">if</span><span class="o">=</span>/dev/urandom <span class="nv">of</span><span class="o">=</span>mnt-lab/file-<span class="nv">$i</span>.bin <span class="nv">bs</span><span class="o">=</span>1M <span class="nv">count</span><span class="o">=</span>2 <span class="nv">status</span><span class="o">=</span>none
  <span class="nb">sync
  sleep </span>1
<span class="k">done</span>
</code></pre></div></div>

<p>İzleme ekranında bazı byte dizilerinin değiştiğini göreceksiniz. Bunlar her zaman “dosya içeriği” değildir; çoğunlukla inode, dizin girdisi, blok bitmap’i gibi meta veri değişikliklerinin journal kayıtlarıdır.</p>

<table>
  <thead>
    <tr>
      <th>Araç</th>
      <th>Görevi</th>
      <th>Neden kullanıyoruz?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">dumpe2fs</code></td>
      <td>ext4 süper blok bilgisini okur</td>
      <td>Blok boyutunu öğrenmek için</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">debugfs</code></td>
      <td>ext dosya sistemini inceler</td>
      <td>Journal inode’unun bloklarını bulmak için</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">dd</code></td>
      <td>Ham blok okur/yazar</td>
      <td>Journal bölgesini doğrudan okumak için</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">hexdump</code></td>
      <td>Byte’ları okunabilir gösterir</td>
      <td>Değişimleri gözlemlemek için</td>
    </tr>
  </tbody>
</table>

<p>Buradaki önemli nokta şudur: ext4 journal’ı bir metin günlüğü değildir; insanlar için değil, dosya sisteminin kendisi için tasarlanmış ikili bir yapıdır. Yani ekranda anlamlı cümleler değil, işlem kayıtlarının ham temsillerini görürsünüz. Yine de yazma yaptıkça bu alanın değiştiğini izlemek, journal fikrini soyut bir kavram olmaktan çıkarır.</p>

<p>Deney bitince temizleyin:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>umount mnt-lab
<span class="nb">rmdir </span>mnt-lab
<span class="nb">rm </span>ext4-lab.img
</code></pre></div></div>

<p>Bu küçük proje sayesinde ext4’ün “önce not al, sonra uygula” mantığını canlı gözlemledik. Dosya sistemleri sessiz çalışır; ama doğru araçlarla bakınca oldukça konuşkandırlar.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Proje" /><category term="ext4" /><category term="linux" /><category term="dd" /><category term="hexdump" /><category term="dosya-sistemi" /><summary type="html"><![CDATA[ext4 dosya sisteminde bir dosya yazdığınızda verinin diske “hop diye” gitmediğini bilmek, Linux’un perde arkasını anlamak için harika bir başlangıçtır. Bu yazıda güvenli bir loop imaj üzerinde ext4 günlük bölgesini bulup, yazma işlemi sırasında dd ve hexdump ile anlık izleyen küçük bir Bash betiği hazırlayacağız. Gerçek diskinize dokunmadan, dosya sisteminin kalp atışlarını dinleyeceğiz.]]></summary></entry><entry><title type="html">GDB Python ile Yığındaki Stringleri Avlayan Renkli Komut Yazmak</title><link href="https://sonsuzus.github.io/posts/gdb-python-ile-yigindaki-stringleri-avlayan-renkli-komut-yazmak/" rel="alternate" type="text/html" title="GDB Python ile Yığındaki Stringleri Avlayan Renkli Komut Yazmak" /><published>2026-07-22T00:00:00+00:00</published><updated>2026-07-22T00:00:00+00:00</updated><id>https://sonsuzus.github.io/posts/gdb-python-ile-yigindaki-stringleri-avlayan-renkli-komut-yazmak</id><content type="html" xml:base="https://sonsuzus.github.io/posts/gdb-python-ile-yigindaki-stringleri-avlayan-renkli-komut-yazmak/"><![CDATA[<p>Debug oturumunda bazen en değerli ipucu, register’larda değil yığının arasında saklanan minicik bir stringdir: bir token, hata mesajı, dosya yolu ya da “buradayım!” diye bağıran bir parola. GNU Debugger, Python API’si sayesinde yalnızca komut çalıştırdığımız bir araç olmaktan çıkar; kendi mini dedektif komutlarımızı yazabileceğimiz genişletilebilir bir platforma dönüşür.
``
Bu yazıda GDB’ye özel bir komut ekleyerek çalışan programın <strong>stack/yığın</strong> bellek bölgesini tarayacak, yazdırılabilir karakterlerden oluşan stringleri bulacak ve terminalde renklendirerek göstereceğiz. Ama önce sahneyi kuralım: yığın, fonksiyon çağrıları sırasında yerel değişkenlerin, dönüş adreslerinin ve geçici verilerin tutulduğu bellek alanıdır. Çoğu mimaride yığın aşağı doğru büyür; yani yeni veri eklendikçe adresler küçülür. Basitçe düşünürsek bir tarama aralığı için \(N = end - start\) bayt okuruz ve ardışık yazdırılabilir karakterleri string adayı kabul ederiz.</p>

<table>
  <thead>
    <tr>
      <th>Bölge</th>
      <th>Tipik İçerik</th>
      <th>Debug İçin Değeri</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Stack</td>
      <td>Yerel değişkenler, geçici buffer’lar</td>
      <td>Anlık durum ve sızıntı ipuçları</td>
    </tr>
    <tr>
      <td>Heap</td>
      <td>Dinamik ayrılan nesneler</td>
      <td>Uzun yaşayan veri yapıları</td>
    </tr>
    <tr>
      <td>.rodata</td>
      <td>Sabit stringler</td>
      <td>Programın gömülü mesajları</td>
    </tr>
  </tbody>
</table>

<p>GDB’nin Python tarafında en sevdiğimiz oyuncular <code class="language-plaintext highlighter-rouge">gdb.Command</code>, <code class="language-plaintext highlighter-rouge">gdb.selected_inferior()</code> ve <code class="language-plaintext highlighter-rouge">read_memory()</code> fonksiyonlarıdır. <code class="language-plaintext highlighter-rouge">gdb.Command</code> ile yeni komut tanımlarız, inferior dediğimiz şey debug edilen süreçtir, <code class="language-plaintext highlighter-rouge">read_memory()</code> ise belirli adres aralığındaki ham baytları okumamızı sağlar. Linux üzerinde <code class="language-plaintext highlighter-rouge">/proc/&lt;pid&gt;/maps</code> dosyasından <code class="language-plaintext highlighter-rouge">[stack]</code> satırını okuyarak gerçek yığın sınırlarını yakalayabiliriz.</p>

<p>Aşağıdaki betik <code class="language-plaintext highlighter-rouge">stackstrings</code> adlı yeni bir GDB komutu ekler. Minimum uzunluğu parametre olarak verebilir, aksi halde 4 karakterden uzun stringleri listeler. Çıktıda adresler mavi, stringler yeşil renktedir; çünkü debug yaparken biraz neon ışık herkesin hakkı!</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># stackstrings.py
</span><span class="kn">import</span> <span class="n">gdb</span>
<span class="kn">import</span> <span class="n">string</span>

<span class="n">GREEN</span> <span class="o">=</span> <span class="sh">'</span><span class="se">\033</span><span class="s">[92m</span><span class="sh">'</span>
<span class="n">BLUE</span> <span class="o">=</span> <span class="sh">'</span><span class="se">\033</span><span class="s">[94m</span><span class="sh">'</span>
<span class="n">YELLOW</span> <span class="o">=</span> <span class="sh">'</span><span class="se">\033</span><span class="s">[93m</span><span class="sh">'</span>
<span class="n">RESET</span> <span class="o">=</span> <span class="sh">'</span><span class="se">\033</span><span class="s">[0m</span><span class="sh">'</span>

<span class="n">PRINTABLE</span> <span class="o">=</span> <span class="nf">set</span><span class="p">(</span><span class="nf">bytes</span><span class="p">(</span><span class="n">string</span><span class="p">.</span><span class="n">printable</span><span class="p">,</span> <span class="sh">'</span><span class="s">ascii</span><span class="sh">'</span><span class="p">))</span> <span class="o">-</span> <span class="p">{</span><span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0x0c</span><span class="p">}</span>

<span class="k">class</span> <span class="nc">StackStrings</span><span class="p">(</span><span class="n">gdb</span><span class="p">.</span><span class="n">Command</span><span class="p">):</span>
    <span class="sh">'''</span><span class="s">Yığın bölgesindeki yazdırılabilir stringleri bulur: stackstrings [min_len]</span><span class="sh">'''</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="nf">super</span><span class="p">(</span><span class="n">StackStrings</span><span class="p">,</span> <span class="n">self</span><span class="p">).</span><span class="nf">__init__</span><span class="p">(</span><span class="sh">'</span><span class="s">stackstrings</span><span class="sh">'</span><span class="p">,</span> <span class="n">gdb</span><span class="p">.</span><span class="n">COMMAND_DATA</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">get_stack_range</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">inferior</span> <span class="o">=</span> <span class="n">gdb</span><span class="p">.</span><span class="nf">selected_inferior</span><span class="p">()</span>
        <span class="n">pid</span> <span class="o">=</span> <span class="n">inferior</span><span class="p">.</span><span class="n">pid</span>
        <span class="k">if</span> <span class="n">pid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">gdb</span><span class="p">.</span><span class="nc">GdbError</span><span class="p">(</span><span class="sh">'</span><span class="s">Çalışan bir süreç yok. Önce run veya attach kullan.</span><span class="sh">'</span><span class="p">)</span>

        <span class="k">with</span> <span class="nf">open</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="s">/proc/</span><span class="si">{</span><span class="n">pid</span><span class="si">}</span><span class="s">/maps</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">r</span><span class="sh">'</span><span class="p">)</span> <span class="k">as</span> <span class="n">maps</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">maps</span><span class="p">:</span>
                <span class="k">if</span> <span class="sh">'</span><span class="s">[stack]</span><span class="sh">'</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span>
                    <span class="n">region</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="nf">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
                    <span class="n">start_s</span><span class="p">,</span> <span class="n">end_s</span> <span class="o">=</span> <span class="n">region</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="sh">'</span><span class="s">-</span><span class="sh">'</span><span class="p">)</span>
                    <span class="k">return</span> <span class="nf">int</span><span class="p">(</span><span class="n">start_s</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span> <span class="nf">int</span><span class="p">(</span><span class="n">end_s</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
        <span class="k">raise</span> <span class="n">gdb</span><span class="p">.</span><span class="nc">GdbError</span><span class="p">(</span><span class="sh">'</span><span class="s">Stack bölgesi bulunamadı.</span><span class="sh">'</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">invoke</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">,</span> <span class="n">from_tty</span><span class="p">):</span>
        <span class="n">min_len</span> <span class="o">=</span> <span class="nf">int</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">if</span> <span class="n">arg</span><span class="p">.</span><span class="nf">strip</span><span class="p">()</span> <span class="k">else</span> <span class="mi">4</span>
        <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">get_stack_range</span><span class="p">()</span>
        <span class="n">inferior</span> <span class="o">=</span> <span class="n">gdb</span><span class="p">.</span><span class="nf">selected_inferior</span><span class="p">()</span>
        <span class="n">mem</span> <span class="o">=</span> <span class="n">inferior</span><span class="p">.</span><span class="nf">read_memory</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">).</span><span class="nf">tobytes</span><span class="p">()</span>

        <span class="n">found</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nf">len</span><span class="p">(</span><span class="n">mem</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">mem</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">in</span> <span class="n">PRINTABLE</span><span class="p">:</span>
                <span class="n">j</span> <span class="o">=</span> <span class="n">i</span>
                <span class="k">while</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="nf">len</span><span class="p">(</span><span class="n">mem</span><span class="p">)</span> <span class="ow">and</span> <span class="n">mem</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="ow">in</span> <span class="n">PRINTABLE</span><span class="p">:</span>
                    <span class="n">j</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">j</span> <span class="o">-</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="n">min_len</span><span class="p">:</span>
                    <span class="n">raw</span> <span class="o">=</span> <span class="n">mem</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">j</span><span class="p">]</span>
                    <span class="n">text</span> <span class="o">=</span> <span class="n">raw</span><span class="p">.</span><span class="nf">decode</span><span class="p">(</span><span class="sh">'</span><span class="s">ascii</span><span class="sh">'</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="sh">'</span><span class="s">replace</span><span class="sh">'</span><span class="p">)</span>
                    <span class="n">addr</span> <span class="o">=</span> <span class="n">start</span> <span class="o">+</span> <span class="n">i</span>
                    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="si">{</span><span class="n">BLUE</span><span class="si">}</span><span class="s">0x</span><span class="si">{</span><span class="n">addr</span><span class="si">:</span><span class="n">x</span><span class="si">}{</span><span class="n">RESET</span><span class="si">}</span><span class="s">: </span><span class="si">{</span><span class="n">GREEN</span><span class="si">}{</span><span class="n">text</span><span class="si">}{</span><span class="n">RESET</span><span class="si">}</span><span class="sh">'</span><span class="p">)</span>
                    <span class="n">found</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="n">i</span> <span class="o">=</span> <span class="n">j</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>

        <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="si">{</span><span class="n">YELLOW</span><span class="si">}</span><span class="s">Toplam </span><span class="si">{</span><span class="n">found</span><span class="si">}</span><span class="s"> string bulundu. Aralık: 0x</span><span class="si">{</span><span class="n">start</span><span class="si">:</span><span class="n">x</span><span class="si">}</span><span class="s">-0x</span><span class="si">{</span><span class="n">end</span><span class="si">:</span><span class="n">x</span><span class="si">}{</span><span class="n">RESET</span><span class="si">}</span><span class="sh">'</span><span class="p">)</span>

<span class="nc">StackStrings</span><span class="p">()</span>
</code></pre></div></div>

<p>Kullanmak için betiği kaydedip GDB içinde yüklemek yeterli:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gdb ./program
<span class="o">(</span>gdb<span class="o">)</span> run
<span class="o">(</span>gdb<span class="o">)</span> <span class="nb">source </span>stackstrings.py
<span class="o">(</span>gdb<span class="o">)</span> stackstrings 6
</code></pre></div></div>

<p>Buradaki algoritma oldukça basittir: belleği soldan sağa tarar, karakter <code class="language-plaintext highlighter-rouge">PRINTABLE</code> kümesindeyse bir koşu başlatır, koşu uzunluğu minimum değeri geçerse sonuç üretir. Zaman karmaşıklığı \(O(N)\), bellek maliyeti ise okunan yığın kadar yani \(O(N)\) kabul edilir. Büyük yığınlarda parça parça okuma yapılabilir; fakat öğretici olması için tek parça okuma daha anlaşılırdır.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">/proc/pid/maps</code> ile sınır bulma</td>
      <td>Gerçek stack aralığını tarar</td>
      <td>Linux odaklıdır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">$sp</code> çevresini tarama</td>
      <td>Taşınabilir fikre daha yakındır</td>
      <td>Tüm yığını kaçırabilir</td>
    </tr>
    <tr>
      <td>Sabit adres aralığı</td>
      <td>Hızlı test edilir</td>
      <td>ASLR nedeniyle kırılgandır</td>
    </tr>
  </tbody>
</table>

<p>Bu komut özellikle CTF, tersine mühendislik, exploit geliştirme ve “ben bu değişkene ne zaman ne yazdım?” soruşturmasında işe yarar. Yine de dikkat: Stack içinde gördüğünüz her karakter dizisi anlamlı string değildir. Rastgele baytlar bazen tesadüfen okunabilir karakterlere dönüşebilir. Bu yüzden bulunan sonuçları bağlamla, register’larla ve backtrace ile birlikte değerlendirmek gerekir.</p>

<p>Sonuç olarak GDB’nin Python API’si, debugger’ı kişisel bir analiz laboratuvarına çevirir. Bugün stack stringlerini renklendirdik; yarın heap tarayıcı, otomatik breakpoint raporlayıcı ya da şüpheli pointer avcısı yazabilirsiniz. Debug dünyasında büyüteç sizde, Python ise büyütecin LED ışığıdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Program" /><category term="gdb" /><category term="python" /><category term="debugging" /><category term="stack" /><category term="reverse-engineering" /><summary type="html"><![CDATA[Debug oturumunda bazen en değerli ipucu, register’larda değil yığının arasında saklanan minicik bir stringdir: bir token, hata mesajı, dosya yolu ya da “buradayım!” diye bağıran bir parola. GNU Debugger, Python API’si sayesinde yalnızca komut çalıştırdığımız bir araç olmaktan çıkar; kendi mini dedektif komutlarımızı yazabileceğimiz genişletilebilir bir platforma dönüşür.]]></summary></entry></feed>