Go Veri Tipleri – Slice

Bu yazının konusu Go’da en çok kullanacağımız veri tiplerinden biri olan Slice. Gelin detaylara geçelim…


Go Veri Tipleri – Slice

Kapak fotoğraf Lisa tarafından Pexels ‘de paylaşılmıştır.

Kod örnekleri Microsoft Learn – Explore Slices

Bir önceki yazıda Go’da string, integer, float, complex, boolean ve array veri tiplerini inceledik. Bundan sonraki veri tiplerimiz (slice, map, struct) biraz daha geniş içerikli olacağı için ayrı yazılarda inceleyeceğiz.

Bu yazının konusu da Go’da en çok kullanacağımız veri tiplerinden biri olan Slice. Slice’larda Array’ler gibi aynı tipteki bir dizi elemanı saklamaya yarayan veri tipleri. Fakat Array’lerin boyutu sabitken, Slice’ların boyutu çalışma esnasında değiştirilebiliyor.

Slice’lar Array ya da bir başka Slice’ı esas alan veri tipleri. Temel olarak bir Array ya da bir başka Slice’ın bir bölümüne atıfta bulunan, onun bir dilimini alan yapılar. Kolaylık olması açısından buna “atıfta bulunulan dizi” diyelim. Bir slice atıfta bulunduğu dizinin sadece bir bölümünü ya da tamamını temsil ediyor olabilir.

Slice’lar 3 bileşenden oluşurlar:

  • Atıfta bulunulan dizideki erişilmek istenen ilk elemanın işaretçisi (pointer). Bu illa ki atıfta bulunulan dizinin ilk elemanı olmak zorunda değildir. ( Ama olabilir de )
  • Slice ‘ın boyutu
  • Slice ‘ın kapasitesi

Slice nasıl tanımlanır?

En basit haliyle, büyüklüğünü belirtmediğiniz bir array tanımladığınızda bir slice tanımlamış olursunuz.

Örnek bir slice tanımı yapalım:

package main

import "fmt"

func main() {
    months := []string{"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"}
    fmt.Println("Aylar   :", months)
    fmt.Println("Boyut   :", len(months))
    fmt.Println("Kapasite:", cap(months))
}

Kodu çalıştırdığımızda şu sonucu alacağız:

Aylar   : [Ocak Şubat Mart Nisan Mayıs Haziran Temmuz Ağustos Eylül Ekim Kasım Aralık]
Botu    : 12
Kapasite: 12

Burada aklınıza şu gelmiş olabilir: “Slice boyutu ve kapasitesinin farkı nedir?” Bunu bir örnekle anlatmak daha kolay oalcaktır;

package main

import "fmt"

func main() {
    months := []string{"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"}
    quarter1 := months[0:3]
    quarter2 := months[3:6]
    quarter3 := months[6:9]
    quarter4 := months[9:12]
    fmt.Println(quarter1, len(quarter1), cap(quarter1))
    fmt.Println(quarter2, len(quarter2), cap(quarter2))
    fmt.Println(quarter3, len(quarter3), cap(quarter3))
    fmt.Println(quarter4, len(quarter4), cap(quarter4))
}

Kodun çıktısı şöyle olacak;

[Ocak Şubat Mart] 3 12
[Nisan Mayıs Haziran] 3 9
[Temmuz Ağustos Eylül] 3 6
[Ekim Kasım Aralık] 3 3

Dikkat ederseniz her birinin boyutu 3 iken, kapasiteleri farklı. Slice’ı tanımlarken başlangıç pozisyonunu ve uzunluğunu belirtiyoruz. Slice boyutu belirlediğimiz boyutken, kapasitesi açık uçlu diyebiliriz ve slice boyutumuzun nereye kadar uzayabileceğini gösteriyor. Kapasite değeri Slice’ı nereye kadar uzatabileceğimizi gösteriyor. Örneğin;

package main

import "fmt"

func main() {
    months := []string{"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"}
    quarter2 := months[3:6]
    quarter2Extended := quarter2[:4]
    fmt.Println(quarter2, len(quarter2), cap(quarter2))
    fmt.Println(quarter2Extended, len(quarter2Extended), cap(quarter2Extended))
}

Bu kodla quarter2’yi ilk elemanından başlatarak uzunluğunu 3’ten 4’e çıkartabiliyoruz..

[Nisan Mayıs Haziran] 3 9
[Nisan Mayıs Haziran Temmuz] 4 9

Slice’a eleman eklemek

Şu ana kadar Slice’ın Array’lere benzer olan kısımlarını ve bir Array’i temel alarak nasıl slice oluşturabileceğimizi öğrendik. Fakat Slice’ın Array’e göre önemli özellikleri de var. En önemlisi Slice’ları boyutu Array’ler gibi sabit değil, aksine dinamik. Bir Slice oluşturduktan sonra bu Slice’a yeni elemanlar ekleyebilir ve oluşturduktan sonra slice boyutunu değiştirebilirsiniz.

Go’da slice’a bir eleman eklemek için append(slice, eleman) komutunu kullanıyoruz. Append foksiyonuna değiştirilecek slice’ı ve eklenecek elemanı gönderdiğimizde bize yeni eleman eklenmiş slice’ı geri döndürecektir.

append fonksiyonunun nasıl çalıştığını bir kodla inceleyelim;

package main

import "fmt"

func main() {
    var numbers []int
    for i := 0; i < 10; i++ {
        numbers = append(numbers, i)
        fmt.Printf("%d\tcap=%d\t%v\n", i, cap(numbers), numbers)
    }
}

Bu kodun çıktısı da şöyle olacaktır;

0       cap=1   [0]
1       cap=2   [0 1]
2       cap=4   [0 1 2]
3       cap=4   [0 1 2 3]
4       cap=8   [0 1 2 3 4]
5       cap=8   [0 1 2 3 4 5]
6       cap=8   [0 1 2 3 4 5 6]
7       cap=8   [0 1 2 3 4 5 6 7]
8       cap=16  [0 1 2 3 4 5 6 7 8]
9       cap=16  [0 1 2 3 4 5 6 7 8 9]

Bu çıktıda dikkat çekici olan üçüncü adımdan sonra slice kapasitesindeki değişimdir. Farkındaysanız 2 olan slice boyutu yetersiz geldiği için otomatik olarak arttırılıyor, önce 4’e, sonra 8’e ve en son olarak da 16’ya çıkıyor.

Görüldüğü üzere slice kapasitesi yetersiz olduğunda Go otomatik olarak kapasiteyi iki katına çıkartıyor.

Slice’dan eleman çıkartmak

Go’da slice’lardan eleman çıkartmak için hazır bir fonksiyon yok. Bunun yerine işlemi çıkartacağımız elemanın olmadığı yeni bir slice oluşturarak yapıyoruz.

Örnek kod ve çıktısı:

package main

import "fmt"

func main() {
    letters := []string{"A", "B", "C", "D", "E"}
    remove := 2

	if remove < len(letters) {

		fmt.Println("Önce", letters)

		letters = append(letters[:remove], letters[remove+1:]...)

		fmt.Println("Sonra", letters)
	}

}
Önce [A B C D E]
Sonra [A B D E]

Slice’ların kopyalarını oluşturmak

Go’da slice’ların kopyalarını oluşturmak için hazır copy(dst, src []Type) fonksiyonunu kullanabilirsiniz. Copy fonksiyonuna hedef slice’ı ve kaynak slice’ı vererek kopyalayabilirsiniz. Örneğin;

slice2 := make([]string, 3)
copy(slice2, letters[1:4])

Neden Slice’ın kopyasını oluşturmalıyız? Bir slice’da değişiklik yaptığınızda aslında slice’ı değil, slice’ın baz aldığı array’i değiştirirsiniz. Eğer o array’i esas alan başka slice’larınız varsa onlar da değişmiş olur. Bunu istemediğimiz durumlarda Slice’ın kopyasını oluşturup onun üzerinde çalışabilirsiniz.

Bir sonraki yazıda Go’da Map veri tipini inceleyeceğiz.

Bu Yazıda Yapılan Değişiklikler
  • 11.05.2022: Yazı özeti düzenlendi.

Bir soru, öneri ya da yorumunuz mu var?

Evren Bal

Ben Evren BAL

1996'dan beri ‘Internet canlısıyım!’

Evren Bal Hakkında daha fazla bilgi.

Tanışmak isterseniz hemen sosyal medyadan iletişime geçebilirsiniz.

Bana Ulaşın

Bana Ulaşın

  • Bir sorunuz mu var?
  • Yazıda bir hata mı farkettiniz?
  • Sayfa ile ilgili bir öneriniz mi var?
  • Yazmamı önereceğiniz bir konu mu var?

Lütfen iletişim formunu kullanarak veya sosyal medya hesaplarımdan bana ulaşın.

Digital Ocean Logo

VPS sunucusu denemek ister misiniz?

Digital Ocean&apos;a referans bağlantımdan kayıt olarak yeni oluşturacağınız hesabınızı 60 gün geçerli 100$ kredi ile açabilirsiniz. Bu miktar yüksek performanslı VPS&apos;leri bile denemeniz için yeterlidir.

Yapacağınız onca kurulumun boşa gitmemesi için benim tavsiyem uzun vadede kullanabileceğiniz özellik ve maliyetlerde bir sunucu oluşturmanızdır.

Ücretsiz 100$ kredi bağlantısı

60 günlük denemeniz sonunda eğer devam etmek istemezseniz hiç bir ücret ödemeyeceksiniz. Hizmeti kullanmaya devam etmek isterseniz harcamanız 25$&apos;a ulaştığında benim hesabıma da 25$ kredi yüklenecektir.

Diğer bir deyişle, siz 100$ ücretsiz krediyi her halükarda kazanırken, daha sonra ücretli devam etmeye karar verirseniz ben de 25$ kredi kazanacağım.

Copyright © 2022 - Evren BAL