1 Go Dilinin Veri Tiplerine Giriş

Go dilinde, veri tipleri programlamanın temelini oluşturur ve değişkenlerin depolayabileceği veri biçimini belirler. Go dilinin sağladığı temel veri tipleri genellikle aşağıdaki kategorilere ayrılır:

Veri Tipi Açıklama Bellek Kullanımı
bool Doğru veya yanlışı depolamak için kullanılan Mantıksal tip 1 byte
int, uint İmzalı ve imzasız tamsayılar, varsayılan boyut sistem platformuna bağlıdır 4 veya 8 byte
int8, uint8 8-bit imzalı ve imzasız tamsayılar 1 byte
int16, uint16 16-bit imzalı ve imzasız tamsayılar 2 byte
int32, uint32 32-bit imzalı ve imzasız tamsayılar 4 byte
int64, uint64 64-bit imzalı ve imzasız tamsayılar 8 byte
float32 32-bit kayan noktalı sayı 4 byte
float64 64-bit kayan noktalı sayı 8 byte
complex64 32-bit gerçek ve hayali bölümleri olan Karmaşık sayı 8 byte
complex128 64-bit gerçek ve hayali bölümleri olan Karmaşık sayı 16 byte
byte uint8’e benzer 1 byte
rune int32’ye benzer, Unicode kod noktasını temsil eder 4 byte
string Dize tipi Dizenin uzunluğuna bağlı olarak değişir
error Hata arayüzü, hata bilgisini döndürmek için kullanılır Sabit boyutta değildir

Bu tipler farklı ihtiyaçlara göre seçilebilir, örneğin sayısal hesaplamalar, metin işleme veya mantıksal kontrol.

2 Tamsayı Veri Tipleri

2.1 Tamsayı Tiplerinin Genel Bakışı

Go dilinde birden fazla yerleşik tamsayı tipi bulunur, şu şekilde sınıflandırılır:

  • İmzalı tamsayılar: int8, int16, int32 (veya rune), int64 ve int
  • İmzasız tamsayılar: uint8 (veya byte), uint16, uint32, uint64 ve uint

int ve uint'in boyutları 32 bit sistemlerde 4 byte, 64 bit sistemlerde ise 8 byte'dır. Tamsayı veri tiplerinin değer aralıkları aşağıdaki tabloda gösterilir:

Tip Değer Aralığı
int8 -128 ile 127 arası
uint8 0 ile 255 arası
int16 -32768 ile 32767 arası
uint16 0 ile 65535 arası
int32 -2147483648 ile 2147483647 arası
uint32 0 ile 4294967295 arası
int64 -9223372036854775808 ile 9223372036854775807 arası
uint64 0 ile 18446744073709551615 arası

2.2 Tamsayı Değişkenleri Kullanma

Tamsayı değişkeni tanımlamanın temel sözdizimi aşağıdaki gibidir:

var degisken_adi veri_tipi = baslangic_degeri

Örnek kod:

package main
import "fmt"

func main() {
    var a int = 10 // İmzalı tamsayı değişkeni
    var b uint = 20 // İmzasız tamsayı değişkeni
    var c int8 = -128 // En küçük int8 değeri
    fmt.Println(a, b, c)
}

2.3 Tamsayı İşlemleri

Go dilinde toplama (+), çıkarma (-), çarpma (*), bölme (/) ve mod (%) gibi yaygın aritmetik operatörlerini destekler. Ayrıca, bit düzeyinde operatörleri de destekler; ve, (&), veya (|), XOR (^), sol kaydırma (<<) ve sağ kaydırma (>>).

package main
import "fmt"

func main() {
    x := 10
    y := 3

    // Aritmetik işlemler
    fmt.Println(x + y) // Toplama
    fmt.Println(x - y) // Çıkarma
    fmt.Println(x * y) // Çarpma
    fmt.Println(x / y) // Bölme
    fmt.Println(x % y) // Mod

    // Bit düzeyinde işlemler
    fmt.Println(x & y)  // Bitwise AND
    fmt.Println(x | y)  // Bitwise OR
    fmt.Println(x ^ y)  // Bitwise XOR
    fmt.Println(x << 1) // 1 sola kaydırma
    fmt.Println(x >> 1) // 1 sağa kaydırma
}

3.1 Kayan Noktalı Veri Türlerinin Genel Bakışı

Go dilinde kayan noktalı tipler float32 ve float64 olarak bulunur, bunlar sırasıyla 32-bit ve 64-bit kayan noktalı veriye karşılık gelir. Genellikle daha büyük bir aralık ve daha doğru bir hassasiyet sunması nedeniyle float64'ün kullanılması önerilir.

  • float32, yaklaşık olarak 23 anlamlı bit sağlar ve yaklaşık 7 ondalık basamağın hassasiyetini sunar.
  • float64, yaklaşık olarak 52 anlamlı bit sağlar ve yaklaşık 16 ondalık basamağın hassasiyetini sunar.

3.2 Kayan Noktalı Değişkenlerin Kullanımı

Kayan noktalı değişkenler, doğrudan sayısal değerlerin verilmesi veya var anahtar kelimesinin kullanılmasıyla bildirilebilir:

package main
import "fmt"

func main() {
    var f1 float32 = 3.14 // float32 tipi açıkça belirtilmiş
    f2 := 3.14            // Otomatik olarak float64 tipi olarak çıkarılmış
    fmt.Println(f1, f2)
}

3.3 Kayan Noktalı Aritmetik ve Sorunlar

Kayan noktalı aritmetik işlemleri hassasiyet kaybına neden olabilir. Özellikle çok yakın sayıları çıkarmak gibi yüksek hassasiyetli işlemler, genellikle bir sorun teşkil eder.

package main
import "fmt"

func main() {
    f1 := .1
    f2 := .2
    f3 := f1 + f2
    fmt.Println(f3) // Hassasiyet sorunlarından dolayı beklenen .3 değeri elde edilmeyebilir

    // Biçimlendirilmiş çıktı kullanarak hassasiyet sorunlarını düzeltme
    fmt.Printf("%.1f\n", f3) // Çıktı .3 olarak düzeltilmiştir
}

4 Mantıksal Veri Türü

4.1 Mantıksal Veri Türünün Genel Bakışı

Boolean, en basit veri tipidir ve yalnızca true (doğru) ve false (yanlış) olmak üzere iki değere sahip olabilir. Koşullu ifadeler ve döngü kontrol yapılarında çok önemli bir konuma sahiptir.

4.2 Mantıksal Değişkenlerin Kullanımı

Mantıksal değişkenlerin bildirimi ve kullanımı:

package main
import "fmt"

func main() {
    var success bool = true
    var fail bool = false
    fmt.Println("İşlem başarılı:", success)
    fmt.Println("İşlem başarısız:", fail)
}

Mantıksal değerler genellikle koşullu ifadelerde kullanılır:

package main
import "fmt"

func main() {
    a := 10
    b := 20
    fmt.Println("a == b:", a == b) // false
    fmt.Println("a < b:", a < b)   // true
}

5 Dize Veri Türü

5.1 Dize Genel Bakışı

Bir dize, karakterlerin bir koleksiyonudur. Go dilinde dizeler değiştirilemezdir. Her dize, temel bayt dizisine bir işaretçi ve uzunluk içerir. Dizeler, baytlar da dahil olmak üzere herhangi bir veriyi içerebilir.

5.2 Dize Değişkenlerinin Kullanımı

Dize değişkenleri genellikle çift tırnak " kullanılarak bildirilir, ancak çok satırlı dizeler oluşturmak için geri tek tırnaklar ` de kullanılabilir:

package main
import "fmt"

func main() {
    var s1 string = "merhaba"
    s2 := "dünya"
    s3 := `Bu, 
    çok satırlı 
    bir dizedir`
    fmt.Println(s1)
    fmt.Println(s2)
    fmt.Println(s3)
}

Bir dize oluşturulduktan sonra, içeriği değiştirilemez. Aşağıdaki işlem hatalıdır ve derleme hatasına neden olur:

s := "merhaba"
s[] = 'M` // Derleme hatası: dize içeriği değiştirilemez

5.3 Dize İşlemleri

Dizeler programlamada oldukça yaygın ve önemlidir. Go dilinde dize manipülasyonu için zengin bir dizi yerleşik fonksiyon sağlanmaktadır. İşte bazı sıkça kullanılan işlemler.

5.3.1 Dize Birleştirme

Go dilinde, dize birleştirmek için en açık yöntem olan artı işareti (+) operatörünü kullanabilirsiniz. Ayrıca, birden çok dizenin sıkça birleştirilmesi durumunda daha iyi performans için strings.Builder'ın kullanılması önerilir.

package main

import (
    "fmt"
    "strings"
)

func main() {
    // + kullanarak dizeleri birleştirme
    hello := "Merhaba, "
    world := "Dünya!"
    result := hello + world
    fmt.Println(result) // Çıktı: Merhaba, Dünya!

    // strings.Builder kullanarak dizeleri birleştirme
    var sb strings.Builder
    sb.WriteString("Merhaba, ")
    sb.WriteString("Dünya!")
    fmt.Println(sb.String()) // Çıktı: Merhaba, Dünya!
}

5.3.2 Dize Ayırma

Dize ayırma, belirtilen ayraç temel alınarak dizeyi bir dilime ayıran strings.Split fonksiyonu kullanılarak yapılabilir.

package main

import (
    "fmt"
    "strings"
)

func main() {
    // Bir dize tanımla
    cumle := "Go, açık kaynaklı bir programlama dilidir"

    // Diziyi boşluk karakterine göre ayır
    kelimeler := strings.Split(cumle, " ")
    for _, kelime := range kelimeler {
        fmt.Printf("%s\n", kelime)
    }
    // Çıktı:
    // Go,
    // açık
    // kaynaklı
    // bir
    // programlama
    // dilidir
}

5.3.3 İndeks Erişimi

Go'da bir dize, değişmez bir bayt dizisidir. Belirli baytlara erişmek için indeksleme kullanabilirsiniz. Ancak, bir dize çoklu baytlı karakterler içerebileceğinden (örneğin UTF-8 kodlanmış karakterler), doğrudan indeksleme beklenen tek bir karakteri veremeyebilir.

package main

import "fmt"

func main() {
    s := "Merhaba, 世界"
    for i := 0; i < len(s); i++ {
        fmt.Printf("%d: %x\n", i, s[i])
    }
    // Not: Bu, baytın onaltılık temsilini, karakterleri değil, çıkaracaktır
}

Diziyi karakter bazında dolaşmak için range döngüsünü kullanabilirsiniz.

package main

import "fmt"

func main() {
    s := "Merhaba, 世界"
    for indeks, runeDegeri := range s {
        fmt.Printf("%d: %U '%c'\n", indeks, runeDegeri, runeDegeri)
    }
    // Çıktı: her karakter için indeks, Unicode kodlaması ve karakter kendisi
}

5.3.4 Uzunluğu Almak

len fonksiyonu bir dizenin uzunluğunu, yani temel bayt dizisinin uzunluğunu alabilir. UTF-8 dizeler için, karakter sayısını (runeleri) almanız gerekiyorsa, utf8.RuneCountInString fonksiyonunu kullanmalısınız. Bu, çoklu baytlı karakterleri doğru şekilde işleyebilir.

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "Merhaba, 世界"
    fmt.Println("Bayt uzunluğu:", len(s)) // Bayt uzunluğunu çıkar
    fmt.Println("Runelerin uzunluğu:", utf8.RuneCountInString(s)) // Karakter uzunluğunu çıkar
}

Yukarıdaki örnekte görebileceğimiz gibi, Go dilinin dize işlemleri için zengin bir kütüphane fonksiyonları sağladığı, çeşitli dize işlemlerini kolayca gerçekleştirmeyi sağladığı görülmektedir. Kodlarken, özellikle ASCII olmayan karakter setleriyle uğraşırken baytlar ile karakterler arasındaki ayrımı dikkate almaya özen göstermek önemlidir.