Golang 101: Yapılar (Structs)
Tags: go, struct
Published: 2021-10-29 14:24:27

Yapı `struct` nesne benzeri gruplama için kullanılır. Bir çok alanda kullanılırlar örn database işlemlerinde, json/xml çıktılarında vb.

```golang
package main

import "fmt"

// Yapı
type Ogrenci struct {
	ad    string
	soyad string
	yas   int
	sinif string
}

// İç içe Yapılar
type Laptop struct {
	islemci    string
	ekranKarti string
	disk       string
	ram        int
}
type Uretici struct {
	firma  string
	model  string
	Laptop // yapı
}

func main() {

	// Boş yapı oluşturma
	ogr := new(Ogrenci)
	fmt.Println(ogr)

	// Yapıya Değer Atama
	fmt.Println(Ogrenci{"Aydın", "Yakar", 40, "3A"})

	// Yapıya alan adları ile birlikte değer atama
	fmt.Println(Ogrenci{ad: "Hasan", soyad: "Ünsal", yas: 45, sinif: "5C"})

	// Boş alanlar ile değer atama
	fmt.Println(Ogrenci{ad: "Osman"})

	// Yapıdaki değeri yazdırma
	o := Ogrenci{ad: "Hüseyin", yas: 20}
	fmt.Println(o.ad)

	// Yapıyı işaretçi ile kullanmak
	ogrenci := &o
	fmt.Println(ogrenci.ad)

	// İşaret edilen yapıda değişiklik yapılabilir
	ogrenci.yas = 22
	fmt.Println(ogrenci.yas)

	// İşaretçi ile belirtilen değişkenlerin değerleri işaret edilen değişkenin adresidir
	fmt.Println("o değişkeni:", &o, "\nogrenci degişkeni:", &ogrenci)

	// Gömülü yapılar
	laptop := Laptop{islemci: "i7 8750h", ekranKarti: "GTX 1060", disk: "250 gb m2 SSD", ram: 16}
	uretici := Uretici{firma: "Monster Notebook", model: "Tulpar T5 v17.1", Laptop: laptop}
	fmt.Println(laptop, uretici)
}

```
```
&{  0 }
{Aydın Yakar 40 3A}
{Hasan Ünsal 45 5C}
{Osman  0 }
Hüseyin
Hüseyin
22
o değişkeni: &{Hüseyin  22 } 
ogrenci degişkeni: 0xc00000e030
{i7 8750h GTX 1060 250 gb m2 SSD 16} {Monster Notebook Tulpar T5 v17.1 {i7 8750h GTX 1060 250 gb m2 SSD 16}}
```
[çalıştır](https://go.dev/play/p/I2pGkNQ_3pn)

## Yapı Tanımlama
```golang
type Ogrenci struct {
	ad string
	soyad string
	yas  int
	sinif string
}
```
Yapı tanımları `struct` anahtar kelimesi ile yapılır. Ardından alanların türleri girilmelidir.

## İç içe Yapılar
```golang
type Laptop struct {
	islemci string
	ekranKarti string
	disk string
	ram int
}
type Uretici struct {
	firma string
	model string
	Laptop // yapı
}
```
Eğer iç içe yapılar olacak ise eklenen yapı için tür belirtecine gerek yoktur. Eğer dizi olarak atanacak ise `laptop []Laptop` şeklinde de belirtilebilir. 
```golang
	laptop   := Laptop{islemci: "i7 8750h", ekranKarti: "GTX 1060", disk: "250 gb m2 SSD", ram: 16}
	uretici  := Uretici{firma: "Monster Notebook", model: "Tulpar T5 v17.1", Laptop: laptop}
	fmt.Println(laptop, uretici)
```

## Boş Yapı Oluşturma
```golang
	ogr := new(Ogrenci)
```
Boş bir yapı oluşturmak için `new()` fonksiyonu kullanılır. Tüm değerler boş/sıfır (`zero-valued`) olacaktır.

## Yapıya Değer Atama Yöntemleri
```golang
	// Yapıya Değer Atama
	fmt.Println(Ogrenci{"Aydın", "Yakar", 40, "3A"})

	// Yapıya alan adları ile birlikte değer atama
	fmt.Println(Ogrenci{ad: "Hasan", soyad: "Ünsal", yas: 45, sinif: "5C"})

	// Boş alanlar ile değer atama
	fmt.Println(Ogrenci{ad: "Osman"})
```
Yukarıda 3 farklı değer atama yöntemi görülmektedir. İlkinde sırasıyla değerler belirtilmiştir, ikinci yöntemde ise alan adları belirtilmiştir fakat istenirse sırası değiştirilerek de belirtilebilir. Son yöntem ise sadece `ad` atanmış, diğer alanlar boş bırakılmıştır.

# Yapıdaki Değeri Yazdırma
```golang
	o := Ogrenci{ad: "Hüseyin", yas: 20}
	fmt.Println(o.ad)
```
Değişken.alan şeklinde erişim sağlanabilmektedir.

## Yapıyı İşaretçi ile Kullanmak
```golang
	ogrenci := &o
	fmt.Println(ogrenci.ad)

	// İşaret edilen yapıda değişiklik yapılabilir
	ogrenci.yas = 22
	fmt.Println(ogrenci.yas)
```
Değişkeni işaretçi `pointer` ile farklı bir değişkene atayabilirsiniz. Fakat unutulmaması gereken aslında `ogrenci` değişkeninin sadece bir işaretçi olduğu yani `o` değişkeninin adresini barındırdığıdır. Yine de işaret edilen yapıda yapılan değişiklikler diğer değişkeni de değiştirmektedir. Karışık mı oldu? Örneğin aşağıdaki kısmını incelediğiniz de daha net oturacaktır.
```golang
	fmt.Println("o değişkeni:", &o, "\nogrenci degişkeni:", &ogrenci)
```