Go Map ve Struct

Bu yazıda Go programlama dilindeki map ve struct tiplerinden bahsedeceğim

Map

Map key/value yapısıyla ilişkilendirilen unordered bir veri yapısıdır. Map içindeki keyler birbiriyle aynı tipte, valuelar da birbiriyle aynı tipte olmak zorundadır. Key ve value birbirinden farklı tipte olabilir. Key değerleri comparable olmalıdır. Mapin zero valuesu nil dir.

Built-in fonksiyon olan make ile map oluşturabilriz.

drivers :=make(map[string]string])

Ayrıca map anahtar kelimesi ile de başlangıç değerleri ile bir map oluşturabiliriz

drivers := map[string]string{
		"Hamilton" :  "Mercedes-AMG Patronas",
    "Vettel":     "Scuderia Ferrari",
	}
drivers :=make(map[string]string])
drivers["Hamilton"] = "Mercedes-AMG Patronas"
drivers["Vettel"] = "Scudria Ferrari"

Yukarıdaki iki kullanım birbirinin eşdeğeridir.

Map içindeki bir veriye aşağıdaki gibi ulaşılabilir

fmt.Println(drivers["Hamilton"]) // Mercedes-AMG Patronas

Map içinden bir veriyi silmek için built-in delete fonksiyonu kullanılır

delete(drivers, "Vettel") // drivers["Vettel"] değerini siler

Yukarıda bahsettiğimiz map içinden bir veriye erişme ve bir veriyi silme operasyonları, ilgili değer map içinde olmasa dahi güvenli işlemlerdir çünkü map lookup işlemi eğer ilgili key değeri map içinde mevcut değilse, o tipin zero value değerini döner.

	points := map[string]int{
  	"Hamilton" :  347,
    "Bottas":     223,
		"Verstappen": 214,
	}

fmt.Println(points["Vettel"]) //0

Yukarıdaki örnekte Vettel map içinde olmadığı için ekrana int değerinin zero value su olan 0 yazar

Her ne kadar yukarıdaki işlemler zero value değeri dönse de bazı durumlarda ilgili key in map içinde olup olmadığından emin olmak isteriz.

name, ok := drivers["Sainz"]
if !ok {
		//Sainz map içinde yok, name değeri " "
}

Yukarıdaki drivers[“Sainz”] işlemi 2 değer geri döndürür. ilk değer map içindeki ilgili key in değeri, ikinci değer ise boolean tipinde ilgili elemanın map içinde olup olmadığı bilgisidir.

Map unordered list olduğu için her map üzerindeki iteration her zaman aynı sıralama ile olmaz. Eğer map içindeki değerleri sıralı bir şekilde almak istiyorsak, map içindeki key leri ayrıca sıralamak gerekiyor.

drivers := map[string]string{
		"Hamilton":   "Mercedes-AMG Patronas",
		"Verstappen": "Aston Martin Redbull",
		"Vettel":     "Scuderia Ferrari",
		"Norris":     "McLaren",
	}
	
  var names = make([]string, 0, len(drivers))
	for name := range drivers {
		names = append(names, name)
	}

	sort.Strings(names)
	for _, name := range names {
		fmt.Printf("%s\t%s\n", name, drivers[name])
	}

//Hamilton        Mercedes-AMG Patronas
//Norris          McLaren
//Verstappen      Aston Martin Redbull
//Vettel          Scuderia Ferrari

Struct

Struct sıfır veya daha fazla veri türünü tek bir yapı altında gruplayan bir veri türüdür. Struct içindeki her bir değer field olarak adlandırılır. Struct Go’da özel karmaşık türler oluşturmak için kullanılır. Struct tipinin zero value su her bir elemanının zero value sudur

Struct Tanımlama

type Student struct {
		ID      int
		Name    string
		Address string
}

Struct Kullanımı

var furkan Student
s := Student{}

Struct ı başlatırken elemanlarına değer verip de başlatabilirz

s := Student{
		Name:  "Furkan Beğen",
		Email: "[email protected]",
}

Bunu yaparken bütün elamanlara değer vermek zorunda değiliz. İstediğimiz kadar elemana değer vererek sturct ı başlatabiliriz

s := Student{
		Email: "[email protected]",
}

Bir struct ın elemanlarına(field) larına nokta(.) notasyonu ile erişebiliriz

furkan.Name = "Furkan"

Bir struct a aynı struct tipinde bir eleman deklare edemeyiz. Aşağıdaki kod compile olmaz

type Employee struct {
		Name     string
		Email    string
		Salary   int
		Employee Employee
}

Fakat bir struct a aynı struct tipinde elemanı pointer tipinde deklare edebiliriz

type Employee struct {
		Name     string
		Email    string
		Salary   int
		Employee *Employee
}

Struct değerleri fonksiyonlara argüman olarak geçilebilir ve fonksiyonların dönüş değeri olabilir

func giveRaise(e Employee, percent int) int {
	return e.Salary * percent / 100
}

Verimlilik açısından büyük struct tipleri fonksiyonlara parametre olarak geçilecekse veya fonksiyonların dönüş değeri olacaksa pointer kullanılır. Ayrıca pointer kullanımı eğer fonksiyon argümanının değerinde bir değişiklik yapacaksa zorunludur. Çünkü Go dili call-by-value bir dildir ve fonksiyon argümanın kendisini değil bir kopyasını alır.

func giveRaise(e *Employee, percent int) int {
	return e.Salary * percent / 100
}

Struct ın bütün alanları karşılaştırılabilir(comparable) ise struc ın kendisi de karşılaştırılabilirdir. Böylelikle == ve ≠ gibi operatörleri kullanabiliriz. == operatörü iki struct ın karşılıklı alanlarını sırasıyla karşılaştırır.

func main() {
	type Coordinate struct {
		X int
		Y int
		Z int
	}

	c1 := Coordinate{X: 0, Y: 0, Z: 0}
	c2 := Coordinate{X: 1, Y: 0, Z: 0}

	if c1 == c2 {
		fmt.Println("Koordinatlar eşit")
	} else {
		fmt.Println("Koordinatlar eşit değil")
	}
}